Python rounding error with float numbers

I do not know if this is an obvious mistake, but when I ran the Python script to change the simulation parameters, I realized that there were no results with delta = 0.29 and delta = 0.58. When researching, I noticed that the following Python code:

for i_delta in range(0, 101, 1): delta = float(i_delta) / 100 (...) filename = 'foo' + str(int(delta * 100)) + '.dat' 

identical files are generated for delta = 0.28 and 0.29, the same with .57 and .58, the reason is that python returns float (29) / 100 as 0.28999999999999998. But this is not a systematic error, and not what happens to every integer. So I created the following Python script:

 import sys n = int(sys.argv[1]) for i in range(0, n + 1): a = int(100 * (float(i) / 100)) if i != a: print i, a 

And I do not see a single pattern in the numbers for which this rounding error occurs. Why does this happen with these specific numbers?

+15
python
May 13 '11 at 19:48
source share
2 answers

Any number that cannot be constructed from the exact powers of two cannot be represented exactly as a floating point number; he should be close. Sometimes the closest approximation will be less than the actual number.

Read What Every Computer Scientist Should Know About Floating-Point Arithmetic .

+26
May 13 '11 at 19:51
source share

Its very well known due to the nature of floating point numbers .

If you want to do decimal arithmetic, floating point arithmetic, to do this.

eg.

 >>> from decimal import Decimal >>> Decimal(29)/Decimal(100) Decimal('0.29') >>> Decimal('0.29')*100 Decimal('29') >>> int(Decimal('29')) 29 

In the general case, the decimal number probably goes overboard and will still have rounding errors in rare cases when the number does not have a finite decimal representation (for example, any fraction where the denominator is not equal to 1 or divisible by 2 or 5 - decimal base factors (10)). For example:

 >>> s = Decimal(7) >>> Decimal(1)/s/s/s/s/s/s/s*s*s*s*s*s*s*s Decimal('0.9999999999999999999999999996') >>> int(Decimal('0.9999999999999999999999999996')) 0 

So it's best to always round before you float in ints if you don't want to use the floor function.

 >>> int(1.9999) 1 >>> int(round(1.999)) 2 

Another alternative is to use the fraction class from the fractions library, which doesn't come close. (He simply continues to add / subtract and multiply the numerators and denominators as necessary).

+15
May 13 '11 at 19:57
source share



All Articles