From 9c37a8c675de65552001052edf159d6bdfbf18ac Mon Sep 17 00:00:00 2001 From: John Darrington Date: Sat, 24 Mar 2012 07:42:51 +0100 Subject: [PATCH] Histograms: Ensure that the bins are aligned to an odd number of half bin widths This has the benefit that the centres of the bins are aligned to integer multiples of bin widths, and thus the labels are shorter. For example, instead of labels -1.5 -0.5 0.5 1.5 2.5 we get -2 -1 0 1 2 which is more aesthetically pleasing. --- src/math/histogram.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/src/math/histogram.c b/src/math/histogram.c index 0b2369f63c..9b89df6895 100644 --- a/src/math/histogram.c +++ b/src/math/histogram.c @@ -60,31 +60,52 @@ histogram_create (double bin_width, double min, double max) int bins; struct histogram *h = xmalloc (sizeof *h); struct statistic *stat = &h->parent; - double upper_limit, lower_limit; + const double half_bin_width = bin_width / 2.0; + + /* -1 if the lower end of the range contains more unused space + than the upper end. + +1 otherwise. */ + short sparse_end = 0; assert (max >= min); if (max == min) - bin_width = 1; + bin_width = 1; - lower_limit = floor (2 * min / bin_width) - 1; - upper_limit = floor (2 * max / bin_width) + 1; + lower_limit = floor (min / half_bin_width) - 1; + upper_limit = floor (max / half_bin_width) + 1; - /* The range must be an even number of half bin_widths */ + if (remainder (min, half_bin_width > remainder (max, half_bin_width))) + sparse_end = -1; + else + sparse_end = +1; + + /* The range must be an EVEN number of half bin_widths */ if ( (int)(upper_limit - lower_limit) % 2) { /* Extend the range at the end which gives the least unused space */ - if (remainder (min, bin_width / 2.0) > remainder (max, bin_width / 2.0)) + if (sparse_end == +1) lower_limit --; else upper_limit ++; + + /* Now the other end has more space */ + sparse_end *= -1; + } + + /* But the range should be aligned to an ODD number of + half bin widths, so that the labels are aesthetically pleasing ones. */ + if ( (int)lower_limit % 2 == 0) + { + lower_limit += -sparse_end ; + upper_limit += -sparse_end ; } bins = (upper_limit - lower_limit) / 2.0; - upper_limit *= bin_width / 2; - lower_limit *= bin_width / 2; + upper_limit *= half_bin_width; + lower_limit *= half_bin_width; h->gsl_hist = gsl_histogram_alloc (bins); -- 2.30.2