diff --git a/src/rainflow.py b/src/rainflow.py index aafa9f3..5287728 100644 --- a/src/rainflow.py +++ b/src/rainflow.py @@ -157,7 +157,16 @@ def count_cycles(series, ndigits=None, nbins=None, binsize=None): if binsize is not None: nmax = 0 for rng, count in cycles: - n = int(math.ceil(rng / binsize)) # using int for Python 2 compatibility + quotient = rng / binsize + n = int(math.ceil(quotient)) # using int for Python 2 compatibility + + if nbins and n > nbins: + # Due to floating point accuracy we may get n > nbins, + # in which case we move rng to the preceeding bin. + if (quotient % 1) > 1e-6: + raise Exception("Unexpected error") + n = n - 1 + counts[n * binsize] += count nmax = max(n, nmax) diff --git a/tests/test_rainflow.py b/tests/test_rainflow.py index 80fdd31..4dc6199 100644 --- a/tests/test_rainflow.py +++ b/tests/test_rainflow.py @@ -301,3 +301,18 @@ def test_reversals_yield_value(series, cycles, counts, approx): ) def test_reversals_small_series(series, reversals): assert list(rainflow.reversals(series)) == reversals + + +def test_num_bins(): + # This test checks for a bug reported in issue #60 where the + # returned number of bins was different than the nbins argument + # due to floating point accuracy. + series = [ + 0, + 3517.860166127188, + -3093.4966492094213, + 0, + ] + nbins = 100 + result = rainflow.count_cycles(series, nbins=nbins) + assert len(result) == nbins