diff --git a/AUTHORS.rst b/AUTHORS.rst index 32bc31a..4bb9668 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -3,3 +3,4 @@ Iteround is written and maintained by Calvin DeBoer. Authors ``````````````````````` - Calvin DeBoer `@cgdeboer `_ +- Manikandan Nagarajan `@M22an `_ diff --git a/README.rst b/README.rst index c30b76a..661b57f 100644 --- a/README.rst +++ b/README.rst @@ -40,6 +40,12 @@ iterable (list, dict, set, numpy.array, generator): list(y) of numbers places (int): Places for rounding. Number of places each item in the set should be rounded to. + +topline (float, optional): Topline to match + Useful in places where we want the total sum to match a different topline + than the sum of iterable. This can useful in cases where original values + are altered before passing into the saferound method, but the original sum + needs to be maintained. strategy (str, optional): The strategy used to clean up rounding errors 'difference', 'largest', 'smallest'. Defaults to 'difference' diff --git a/iteround/core.py b/iteround/core.py index 10f0b90..a1da7fd 100644 --- a/iteround/core.py +++ b/iteround/core.py @@ -6,7 +6,7 @@ DIFFERENCE = 'difference' -def saferound(iterable, places, strategy=DIFFERENCE, rounder=round): +def saferound(iterable, places, strategy=DIFFERENCE, rounder=round, topline=None): """Rounds an iterable of floats while retaining the original summed value. Function parameters should be documented in the ``Args`` section. The name @@ -39,6 +39,12 @@ def saferound(iterable, places, strategy=DIFFERENCE, rounder=round): rounder method must take 2 arguments, a `float` to be rounded, and an integer for the number of places (with support for negative) + topline (float, optional): Topline to match + Useful in places where we want the total sum to match a different + topline than the sum of iterable. This can useful in cases where + original values are altered before passing into the saferound + method, but the original sum needs to be maintained. + Returns: iterable (same type as input, but with rounded values). @@ -65,7 +71,9 @@ def saferound(iterable, places, strategy=DIFFERENCE, rounder=round): # calculate original sum, rounded, then rounded local sum. local = [Number(i, value) for i, value in enumerate(values)] - orig_sum = _sumnum(local, places, rounder) + orig_sum = (_sumnum(local, places, rounder) + if topline is None else + rounder(topline, places)) [n.round(places, rounder) for n in local] local_sum = _sumnum(local, places, rounder) diff --git a/setup.py b/setup.py index 56021f4..eb1d283 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="iteround", - version="1.0.2", + version="1.0.3", author="Calvin DeBoer", author_email="cgdeboer@gmail.com", description=("Rounds iterables (arrays, lists, sets, etc) " diff --git a/tests/test_saferound.py b/tests/test_saferound.py index 12d4ad4..7741866 100644 --- a/tests/test_saferound.py +++ b/tests/test_saferound.py @@ -2,7 +2,6 @@ import iteround from collections import OrderedDict - class TestSafeRoundMethods(unittest.TestCase): def setUp(self): @@ -79,6 +78,19 @@ def test_over_with_sum(self): out = [0.0, 0.0, 0.0, 10.0, 10.0, 10.0] self.assertListEqual(iteround.saferound(self.in_list, -1), out) + def test_topline(self): + out = [4.0, 3.0, 3.0, 7.0, 5.0, 7.0] + topline = 29 + actual_out = iteround.saferound(self.in_list, 0, topline=topline) + actual_topline = sum(actual_out) + self.assertListEqual(actual_out, out) + self.assertEqual(topline, actual_topline) + + def test_topline_sum(self): + self.assertEqual(sum(iteround.saferound(self.in_list, 0, topline=28)), 28) + self.assertEqual(sum(iteround.saferound(self.in_list, 0, topline=29)), 29) + self.assertEqual(sum(iteround.saferound(self.in_list, 0, topline=30)), 30) + if __name__ == '__main__': unittest.main()