I am learning C++ from a C background, and I was wondering if I could convert this old C program I'd written into C++ as a personal exercise. The original C program is a simple Monte Carlo simulation that simulates a virus spreading throughout a school population.
Currently, my C++ implementation is almost identical to the C version, despite a few minor changes. Given this is a somewhat large block of algorithmically-focused code, I am not looking for specific details, but I was wondering if any of these C constructs could be replaced with more idiomatic C++ versions.
For the record, I am aware of the minor differences, such as the possibility of using iostream
s instead of printf
for the I/O, but I often find C's IO to be more expressive in this situation, anyway. I'm more curious about more general problems.
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <climits>
#include <ctime>
static long NUM_SIMULATIONS;
static int INFECTION_THRESHOLD;
static int uninfected_students = 0;
static int infected_students[] = {0, 0, 0, 0, 0};
void simulate_day();
int run_simulation();
int main(int argc, char** argv) {
srand(time(NULL));
if (argc < 2 || argc > 3) {
printf("usage: maine <rate> [simulations=1000]\n");
exit(EXIT_SUCCESS);
}
double transmission_rate = strtod(argv[1], NULL);
if (transmission_rate <= 0 || transmission_rate > 1) {
fprintf(stderr, "maine: error: rate must be a number in the range (0, 1]\n");
exit(EXIT_FAILURE);
}
INFECTION_THRESHOLD = (int) (RAND_MAX * 0.04 * transmission_rate);
if (argc > 2) {
NUM_SIMULATIONS = strtol(argv[2], NULL, 10);
if (NUM_SIMULATIONS <= 0) {
fprintf(stderr, "maine: error: simulations must be a number in the range (0, %li]\n", LONG_MAX);
exit(EXIT_FAILURE);
}
} else {
NUM_SIMULATIONS = 1000;
}
double infected_students = 0;
int successful_infections = 0;
printf("Running simulation..."); fflush(stdout);
clock_t start_time = clock();
for (int i = 0; i < NUM_SIMULATIONS; i++) {
int simulation = run_simulation();
infected_students += simulation;
if (simulation >= 10)
successful_infections++;
printf("\rRunning simulation... (%06.2f%%)", (double) i / NUM_SIMULATIONS * 100.0);
fflush(stdout);
}
clock_t end_time = clock();
clock_t elapsed_time = end_time - start_time;
// Running simulation... (000.00%)
printf("\rSimulation complete. (%6.2fs)\n", (double) elapsed_time / CLOCKS_PER_SEC);
infected_students /= NUM_SIMULATIONS;
printf("\n");
printf(" Average number of students infected: %8.4f (%05.2f%%)\n", infected_students, infected_students / 300.0 * 100.0);
printf(" Infection probability per student: %15.2f%%\n", (infected_students - 1) / 299.0 * 100.0);
printf(" Number of 'successful infections': %8i (%05.2f%%)\n", successful_infections, (double) successful_infections / NUM_SIMULATIONS * 100.0);
printf("\n");
return 0;
}
int run_simulation() {
uninfected_students = 299;
infected_students[0] = 1;
memset(infected_students + 1, 0, sizeof(*infected_students) * 4);
while (uninfected_students > 0 && (infected_students[0] > 0 || infected_students[1] > 0 || infected_students[2] > 0 || infected_students[3] > 0 || infected_students[4] > 0)) {
simulate_day();
}
return 300 - (uninfected_students < 0 ? 0 : uninfected_students);
}
void simulate_day() {
int contagious_students = infected_students[3] + infected_students[4];
int newly_infected_students = 0;
for (int i = 0; i < contagious_students; i++) {
int current_uninfected = uninfected_students;
for (int j = 0; j < current_uninfected; j++) {
if (rand() >= INFECTION_THRESHOLD) continue;
uninfected_students--;
newly_infected_students++;
}
}
memmove(infected_students + 1, infected_students, sizeof(*infected_students) * 4);
infected_students[0] = newly_infected_students;
}