+ 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 ?

26th Apr 2018, 11:05 AM
Cépagrave
Cépagrave - avatar
37 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.
26th Apr 2018, 1:33 PM
Nevfy
+ 32
many times python surprises me a lot...😀 Cépagrave can u tell me the reason y u r not using round function... round(b,2)
26th Apr 2018, 11:23 AM
🌛DT🌜
🌛DT🌜 - avatar
+ 23
i hope i can make apps with phyton and floats
30th Apr 2018, 11:16 AM
Nina Hendra Putri
Nina Hendra Putri - avatar
+ 12
change print(b) To print(round(b,2))
28th Apr 2018, 3:02 PM
_F1_
_F1_ - avatar
+ 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.
26th Apr 2018, 8:46 PM
Cépagrave
Cépagrave - avatar
+ 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 ?
26th Apr 2018, 11:22 AM
Cépagrave
Cépagrave - avatar
26th Apr 2018, 11:50 AM
Oma Falk
Oma Falk - avatar
+ 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 ?
26th Apr 2018, 11:54 AM
Cépagrave
Cépagrave - avatar
+ 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.
26th Apr 2018, 11:59 AM
Cépagrave
Cépagrave - avatar
+ 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
26th Apr 2018, 11:52 AM
Cépagrave
Cépagrave - avatar
+ 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)
2nd May 2018, 7:44 PM
Kirk Schafer
Kirk Schafer - avatar
+ 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.
26th Apr 2018, 1:58 PM
Cépagrave
Cépagrave - avatar
+ 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 ?
27th Apr 2018, 6:11 AM
Cépagrave
Cépagrave - avatar
+ 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)
1st Jun 2020, 8:36 AM
pariii_kasliwal🎭
pariii_kasliwal🎭 - avatar
+ 5
yes... and if you combine round and format,You are done (-:
26th Apr 2018, 12:00 PM
Oma Falk
Oma Falk - avatar
+ 5
Nevfy indeed best answer Cépagrave : a very i,teresti,g post. Hope more pythonists will read (and upvote)
26th Apr 2018, 2:15 PM
Oma Falk
Oma Falk - avatar
+ 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.
30th Apr 2018, 12:22 AM
Astutewinter
Astutewinter - avatar
+ 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.
27th Apr 2018, 1:51 AM
Nevfy
+ 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
6th May 2018, 9:41 PM
Rick Shiffman
Rick Shiffman - avatar