Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python rounding error with float numbers [duplicate]

Tags:

python

I don't know if this is an obvious bug, but while running a Python script for varying the parameters of a simulation, I realized the results with delta = 0.29 and delta = 0.58 were missing. On investigation, 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' 

generated identical files for delta = 0.28 and 0.29, same with .57 and .58, the reason being that python returns float(29)/100 as 0.28999999999999998. But that isn't a systematic error, not in the sense it 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 can't see any pattern in the numbers for which this rounding error happens. Why does this happen with those particular numbers?

like image 908
jpjandrade Avatar asked May 13 '11 19:05

jpjandrade


People also ask

How do I fix rounding in Python?

To implement the “rounding down” strategy in Python, we can follow the same algorithm we used for both trunctate() and round_up() . First shift the decimal point, then round to an integer, and finally shift the decimal point back.

Why do floats have rounding errors Python?

It's a problem caused when the internal representation of floating-point numbers, which uses a fixed number of binary digits to represent a decimal number. It is difficult to represent some decimal number in binary, so in many cases, it leads to small roundoff errors.

How do you round off floating numbers in Python?

Python has an inbuilt function round(), which will take the float value and round it off. The round() function takes two parameters: Number and Ndigits (optional). Ndigits represent the number of decimal places to round.

Can floating point operations cause round off errors?

Roundoff error caused by floating-point arithmetic Even if some numbers can be represented exactly by floating-point numbers and such numbers are called machine numbers, performing floating-point arithmetic may lead to roundoff error in the final result.


2 Answers

Any number that can't be built from exact powers of two can't be represented exactly as a floating point number; it needs to be approximated. Sometimes the closest approximation will be less than the actual number.

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

like image 57
Mark Ransom Avatar answered Sep 28 '22 07:09

Mark Ransom


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

If you want to do decimal arithmetic not floating point arithmatic there are libraries to do this.

E.g.,

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

In general decimal is probably going overboard and still will 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 1 or divisible by 2 or 5 - the factors of the decimal base (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 its best to always just round before casting floating points to ints, unless you want a 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 approximate. (It justs keeps adding/subtracting and multiplying the integer numerators and denominators as necessary).

like image 36
dr jimbob Avatar answered Sep 28 '22 07:09

dr jimbob