Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Round a Python list of numbers and maintain their sum

I have a list or an array of decimal numbers in Python. I need to round them to the nearest 2 decimal places as these are monetary amounts. But, I need the overall sum to be maintained, i.e. the sum of the original array rounded to 2 decimal places must be equal to the sum of the rounded elements of the array.

Here's my code so far:

myOriginalList = [27226.94982, 193.0595233, 1764.3094, 12625.8607, 26714.67907, 18970.35388, 12725.41407, 23589.93271, 27948.40386, 23767.83261, 12449.81318]
originalTotal = round(sum(myOriginalList), 2)
# Answer = 187976.61

# Using numpy
myRoundedList = numpy.array(myOriginalList).round(2)
# New Array = [ 27226.95    193.06   1764.31  12625.86  26714.68  18970.35  12725.41 23589.93 27948.4   23767.83  12449.81]

newTotal = myRoundedList.sum()
# Answer = 187976.59

I need an efficient way of amending my new rounded array such that the sum is also 187976.61. The 2 pence difference needs to be applied to items 7 and 6 as these have the greatest difference between the rounded entries and the original entries.

like image 585
user2237024 Avatar asked Apr 02 '13 17:04

user2237024


People also ask

How to round the numbers of a list in Python?

Write a Python program to round the numbers of a given list, print the minimum and maximum numbers and multiply the numbers by 5. Print the unique numbers in ascending order separated by space.

How to sum a list of numbers in Python?

Python’s built-in function sum () is an efficient and Pythonic way to sum a list of numeric values. Adding several numbers together is a common intermediate step in many computations, so sum () is a pretty handy tool for a Python programmer.

What does sum () do in Python?

So far, you’ve learned the basics of working with sum (). You’ve learned how to use this function to add numeric values together and also to concatenate sequences such as lists and tuples. In this section, you’ll look at some more examples of when and how to use sum () in your code.

How do you round to the nearest hundredths in Python?

Hundredths place. 12.35. To implement the “rounding up” strategy in Python, we’ll use the ceil () function from the math module. The ceil () function gets its name from the term “ceiling,” which is used in mathematics to describe the nearest integer that is greater than or equal to a given number.


2 Answers

The first step is to calculate the error between the desired result and the actual sum:

>>> error = originalTotal - sum(myRoundedList)
>>> error
0.01999999996041879

This can be either positive or negative. Since every item in myRoundedList is within 0.005 of the actual value, this error will be less than 0.01 per item of the original array. You can simply divide by 0.01 and round to get the number of items that must be adjusted:

>>> n = int(round(error / 0.01))
>>> n
2

Now all that's left is to select the items that should be adjusted. The optimal results come from adjusting those values that were closest to the boundary in the first place. You can find those by sorting by the difference between the original value and the rounded value.

>>> myNewList = myRoundedList[:]
>>> for _,i in sorted(((myOriginalList[i] - myRoundedList[i], i) for i in range(len(myOriginalList))), reverse=n>0)[:abs(n)]:
    myNewList[i] += math.copysign(0.01, n)

>>> myRoundedList
[27226.95, 193.06, 1764.31, 12625.86, 26714.68, 18970.35, 12725.41, 23589.93, 27948.4, 23767.83, 12449.81]
>>> myNewList
[27226.95, 193.06, 1764.31, 12625.86, 26714.68, 18970.359999999997, 12725.42, 23589.93, 27948.4, 23767.83, 12449.81]
>>> sum(myNewList)
187976.61
like image 86
Mark Ransom Avatar answered Sep 25 '22 18:09

Mark Ransom


As noted in an answer by kettlehell, consider the PyPI package iteround. It does not internally use NumPy, however.

>>> from iteround import saferound
>>> saferound([1.0, 2.1, 3.6], places=0)
[1.0, 2.0, 4.0]
like image 21
Asclepius Avatar answered Sep 26 '22 18:09

Asclepius