+ 33
Python and floats
I wrote a very simple code to show the trouble with floating point numbers. a = 0.1 b = 0 for i in range(3): b = a+b print(b) Here is the link if you want to run/modify it : https://code.sololearn.com/cjYE2W2a0eI7/?ref=app it prints : 0.30000000000000004 should be 0.3 What are the ways you pythonists deal with this ?
36 Answers
+ 21
Well, it really depends on your application.
1. If it is enough for you to use round() as @🌛DT🌜proposed, you can deal with it, but it will quickly increase errors of calculations if you perform many different operations.
2. It is much better to perform calculations without rounding the result, but only make the number beauty, when you print it out on the screen using format() as @Oma Falk proposed.
3. However, the only TRUE method to deal with decimal numbers very precisely is to use Decimal library as @Jan Markus said. It increases memory consumption and slows down a bit the calculations speed, but it costs the result! You should use it in all serious applications where the precision of numbers is important.
+ 23
i hope i can make apps with phyton and floats
+ 12
change print(b)
To
print(round(b,2))
+ 10
So, I decided to test this decimal module.
Very interesting !
I will be very scared when using for loops now :-(
https://code.sololearn.com/cSVc29NqF3at/#py
Please don't hesitate to tell me if something is wrong in this code.
It's very strange to see how the difference between python float and decimal after many iterations is not linear, sometimes jumps and then stays quite stable, but most important is so big after around 650 iterations ...
Even more amazing : it suddenly goes back down between 675 and 680 iterations.
It sure depdends on what operations are done in the loop.
+ 9
Thank you Xan,
I already read about the theory behind it, even though what I read was a really short explanation compared to the pdf you propose here. I'll read it to have a more detailed understanding.
But my question is more concrete :
How do you deal with it in a simple code ?
+ 9
@Jan Markus
Thank you, I didn't know this module, will give it a try !
Do you have examples of codes where you've used it ?
+ 8
@Oma Falk
Thank you !
That's actually what I first used and was not happy with (check my updated code to understand why), because it prints the same number of decimals, whenever it's exact values or not.
round() is better for my needs.
+ 7
@🌛DT🌜
Thanks !
round() is ok for most uses, true.
I modified my code : there still is a small problem with
1.0 instead of just 1
+ 7
It's not Python, per se; it's all IEEE-754 binary-encoded floats.
Python uses the function math.fsum() to track accumulated error, using the Shewchuk algorithm.
Docs: "Return an accurate floating point sum of values in the iterable. Avoids loss of precision by tracking multiple intermediate partial sums"
The algorithm: Binary Floating Point Summation Accurate to full precision (Python recipe)
https://code.activestate.com/recipes/393090
"Completely eliminates rounding errors and loss of significance due to catastrophic cancellation during summation" (three approaches)
+ 6
Nevfy
Thank you, this makes a good concluding synthesis to the question that can be useful for other, thus I'll mark it best.
+ 6
Nevfy
Thank you for checking my code (output corrected now). Yes, division by number close to 0 has a strong effect here.
I'll definitely use decimal when cooking with numbers in looping pans !
Do you also use other functions from this module ?
+ 6
Python uses the function math.fsum() to track accumulated error, using the Shewchuk algorithm.
Docs: "Return an accurate floating point sum of values in the iterable. Avoids loss of precision by tracking multiple intermediate partial sums"
The algorithm: Binary Floating Point Summation Accurate to full precision (Python recipe)
https://code.activestate.com/recipes/393090
"Completely eliminates rounding errors and loss of significance due to catastrophic cancellation during summation" (three approaches)
+ 5
yes... and if you combine round and format,You are done (-:
+ 5
The reason this happens is because computers have to be in binary, so 0.1 in binary is 0.00011 (the last 0011 is reoccurring.) Since computers have a finite amount of bits they can store a number *close* to 0.1, but not *exactly* 0.1. This can be avoided by storing the separate decimal places as variables. It takes some more RAM, but is more accurate.
+ 4
You mixed up places for float point and decimal at your output string, but it doesn't really matter.
What counts is how quickly the difference rises between 660 and 670 operations! Now you can see that you should be careful with floating point numbers.
For sure it is not always like that. You picked up very 'resonant' set of operations. I mean that it operates with small numbers, which are close to 0 for some division operation.
But anyway, that's why in real projects, when many iterations have to be performed, I prefer to use decimals.
+ 4
That is just truncation, or round off error in the floating point representation of .3 . Since the processor that your code is runs on has a finite number of bits in each machine word for the mantissa and exponent to represent a floating number and for doing floating point calculations.
Years ago IBM ran in to this problems in programs that did financial calculations, there solution was to add decimal arithmetic instructions to there 360 / 370 line of computers. Look for a decimal module in the python library's