Histogram { protected static <T> List<T> getBucketBoundaries( MathOperations<T> math, T lowerBound, T upperBound, T actualMinimum, T actualMaximum, int bucketCount, int bucketWidthSigFigs ) { lowerBound = math.compare(lowerBound, actualMinimum) < 0 ? actualMinimum : lowerBound; upperBound = math.compare(actualMaximum, upperBound) < 0 ? actualMaximum : upperBound; if (math.compare(lowerBound, upperBound) == 0) { List<T> boundaries = new ArrayList<T>(); boundaries.add(lowerBound); boundaries.add(upperBound); return boundaries; } final boolean extraLowerBucketNeeded = math.compare(lowerBound, actualMinimum) > 0; final boolean extraUpperBucketNeeded = math.compare(actualMaximum, upperBound) > 0; if (extraLowerBucketNeeded) --bucketCount; if (extraUpperBucketNeeded) --bucketCount; T totalWidth = math.subtract(upperBound, lowerBound); int totalWidthScale = math.getExponentInScientificNotation(totalWidth); T roundedLowerBound = math.roundDown(lowerBound, -totalWidthScale); T roundedUpperBound = math.roundUp(upperBound, -totalWidthScale); double finalLowerBound = math.doubleValue(roundedLowerBound); double finalUpperBound = math.doubleValue(roundedUpperBound); double finalBucketCount = bucketCount; double bucketWidth = (finalUpperBound - finalLowerBound) / finalBucketCount; List<T> boundaries = new ArrayList<T>(); if (bucketWidth > 0.0d) { if (extraLowerBucketNeeded) boundaries.add(actualMinimum); double nextBoundary = finalLowerBound; for (int i = 0; i != bucketCount; ++i) { boundaries.add(math.create(nextBoundary)); nextBoundary = nextBoundary + bucketWidth; } boundaries.add(roundedUpperBound); if (extraUpperBucketNeeded) boundaries.add(actualMaximum); } return boundaries; } Histogram( MathOperations<T> operations,
                      List<T> values ); @SafeVarargs  Histogram( MathOperations<T> operations, T... values ); BucketingStrategy getStrategy(); MathOperations<T> getMathOperations(); void setStrategy( double median,
                             double standardDeviation,
                             int sigma ); void setStrategy( T minimum,
                             T maximum ); void setStrategyToDefault(); int getSignificantFigures(); Histogram<T> setSignificantFigures( int significantFigures ); int getBucketCount(); Histogram<T> setBucketCount( int count ); List<Bucket> getBuckets(); long getTotalNumberOfValues(); List<String> getTextGraph( int maxBarLength ); static final int DEFAULT_BUCKET_COUNT; static final int DEFAULT_SIGNIFICANT_FIGURES; }
@Test public void shouldCorrectlyConstructBoundariesWithWindowSmallerThanActualFloats() { List<Float> boundaries = Histogram.getBucketBoundaries(new FloatOperations(), 10.0f, 20.0f, 5.0f, 25.0f, 12, 3); assertNotNull(boundaries); assertEquals(13, boundaries.size()); Float[] expectedBoundaries = {5.0f, 10.0f, 11f, 12f, 13f, 14f, 15f, 16f, 17f, 18f, 19f, 20f, 25f}; assertArrayEquals(expectedBoundaries, boundaries.toArray(new Float[boundaries.size()])); }
@Test public void shouldCorrectlyConstructBoundariesWithWindowSmallerThanActualNarrowlyVaryingFloats() { List<Float> boundaries = Histogram.getBucketBoundaries(new FloatOperations(), 10.00020f, 10.00030f, 10.00011f, 10.00050f, 12, 3); assertNotNull(boundaries); assertEquals(13, boundaries.size()); assertEquals(10.00011f, boundaries.get(0), 0.00001f); assertEquals(10.00020f, boundaries.get(1), 0.00001f); assertEquals(10.00021f, boundaries.get(2), 0.00001f); assertEquals(10.00022f, boundaries.get(3), 0.00001f); assertEquals(10.00023f, boundaries.get(4), 0.00001f); assertEquals(10.00024f, boundaries.get(5), 0.00001f); assertEquals(10.00025f, boundaries.get(6), 0.00001f); assertEquals(10.00026f, boundaries.get(7), 0.00001f); assertEquals(10.00027f, boundaries.get(8), 0.00001f); assertEquals(10.00028f, boundaries.get(9), 0.00001f); assertEquals(10.00029f, boundaries.get(10), 0.00001f); assertEquals(10.00030f, boundaries.get(11), 0.00001f); assertEquals(10.00050f, boundaries.get(12), 0.00001f); }