squiggle.c

Self-contained Monte Carlo estimation in C99
Log | Files | Refs | README

histogram.c (2457B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <float.h>
      4 
      5 #define MAX_SAMPLES 1000000
      6 
      7 int main(int argc, char *argv[]) {
      8     if (argc < 2) {
      9         fprintf(stderr, "Usage: %s number_of_bins\n", argv[0]);
     10         exit(EXIT_FAILURE);
     11     }
     12 
     13     int num_bins = atoi(argv[1]);
     14     if (num_bins <= 0) {
     15         fprintf(stderr, "Number of bins must be a positive integer.\n");
     16         exit(EXIT_FAILURE);
     17     }
     18 
     19     int *bins = calloc(num_bins, sizeof(int));
     20     double *samples = malloc(MAX_SAMPLES * sizeof(double));
     21     if (bins == NULL || samples == NULL) {
     22         fprintf(stderr, "Memory allocation failed.\n");
     23         exit(EXIT_FAILURE);
     24     }
     25 
     26     double value, min_value = DBL_MAX, max_value = -DBL_MAX;
     27     int sample_count = 0;
     28 
     29     // Read numbers from stdin and store them into the samples array
     30     while (sample_count < MAX_SAMPLES && scanf("%lf", &value) != EOF) {
     31         samples[sample_count++] = value;
     32         if (value < min_value) {
     33             min_value = value;
     34         }
     35         if (value > max_value) {
     36             max_value = value;
     37         }
     38     }
     39 
     40     // Avoid division by zero for a single unique value
     41     if (min_value == max_value) {
     42         max_value++;
     43     }
     44 
     45     // Calculate bin width
     46     double range = max_value - min_value;
     47     double bin_width = range / num_bins;
     48 
     49     // Fill the bins with sample counts
     50     for (int i = 0; i < sample_count; i++) {
     51         int bin_index = (int)((samples[i] - min_value) / bin_width);
     52         if (bin_index == num_bins) {
     53             bin_index--; // Last bin includes max_value
     54         }
     55         bins[bin_index]++;
     56     }
     57 
     58     // Calculate the scaling factor based on the maximum bin count
     59     int max_bin_count = 0;
     60     for (int i = 0; i < num_bins; i++) {
     61         if (bins[i] > max_bin_count) {
     62             max_bin_count = bins[i];
     63         }
     64     }
     65     const int MAX_WIDTH = 50; // Adjust this to your terminal width
     66     double scale = max_bin_count > MAX_WIDTH ? (double)MAX_WIDTH / max_bin_count : 1.0;
     67 
     68     // Print the histogram
     69     for (int i = 0; i < num_bins; i++) {
     70         double bin_start = min_value + i * bin_width;
     71         double bin_end = bin_start + bin_width;
     72         printf("  [%4.1f, %4.1f): ", bin_start, bin_end);
     73 
     74         int marks = (int)(bins[i] * scale);
     75         for (int j = 0; j < marks; j++) {
     76             printf("▇");
     77         }
     78         printf(" %d\n", bins[i]);
     79     }
     80 
     81     // Free the allocated memory
     82     free(bins);
     83     free(samples);
     84 
     85     return 0;
     86 }