简体   繁体   中英

How to check if a list of floats adds up to a whole number?

I would like to find the sum of a list of floats and check if it is a whole number or not:

l = [0.85, 0.85, 0.15, 0.15]

The sum of l is 2.0, obviously. But Python does not agree, due to floating point limitations :

> sum(l)
1.9999999999999998

Therefore my method of choice, sum(l).is_integer() , will return False .

What would be a better method to evaluate if lists sum to a whole number?

You can use the decimal package.

>>> from decimal import Decimal
>>> l = [Decimal(x) for x in ['0.85', '0.85', '0.15', '0.15']]
>>> s = sum(l)
>>> s
Decimal('2.00')
>>> s == int(s)
True

You can use a combination of math.isclose and the inbuilt round function.

>>> from math import isclose  
>>> l = [0.85, 0.85, 0.15, 0.15]
>>> s = sum(l)
>>> isclose(s, round(s))
True

When you need exact arithmetic, the best solution is to work with integers only. In this case you could round each of your inputs to 2 or 3 decimal places for the check.

l = [0.85, 0.85, 0.15, 0.15]
number_of_places = 3
multiplier = 10 ** number_of_places
>>> sum(int(round(x*multiplier)) for x in l)
2000
>>> sum(int(round(x*multiplier)) for x in l) % multiplier == 0
True

Apart Decimal, you can also use the fractions module, which will enable handling arbitrary denominators like:

from fractions import Fraction
print(Fraction(1,3) + Fraction(4,7) + Fraction(2,21))

Also works with Fraction('0.85') + Fraction('0.15') or Fraction('2/6') .

Note that the result of adding Fractions is a Fraction, eventually with denominator == 1, so instead of testing is_integer() , you have to replace with a denominator check, or with equality of int conversion:

collection = [Fraction(each) for each in ['0.85', '0.85', '0.15', '0.15']]
sum = sum(collection)
print(sum.denominator == 1)
print(int(sum) == sum)

In some languages including Smalltalk, Fractions are automatically reduced to Integer when denominator is 1, making the code a bit less brittle...

^((1/3) + (4/7) + (2/21)) isInteger

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM