This question already has answers here:
Python rounding error with float numbers [duplicate]
(2 answers)
Closed 9 years ago.
When using list comprehension expression:
[x * 0.1 for x in range(0, 5)]
I expect to get a list like this:
[0.0, 0.1, 0.2, 0.3, 0.4]
However I instead I get this:
[0.0, 0.1, 0.2, 0.30000000000000004, 0.4]
What is the reason behind this?
floats are inherently imprecise in pretty much every language
if you need exact precision use the Decimal class
from decimal import Decimal
print Decimal("0.3")
if you just need them to look pretty just use format strings when displaying
eg :
"%0.2f"%2.030000000000034
if you want to compare them use some threshold
if num1 - num2 < 1e-3 : print "Equal Enough For Me!"
**see abarnert's comments on thresholding ... this is a very simplified example for a more indepth explanation of epsilon thresholding one article I found is here http://www.cygnus-software.com/papers/comparingfloats/Comparing%20floating%20point%20numbers.htm
Additional Reading:
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html (for a detailed explanation)
http://floating-point-gui.de/basic/ (basic tutorial for working with floats in general)
List comprehension does not matter.
>>> 3 * 0.1
0.30000000000000004
>>> 2 * 0.1
0.2
>>> 0.1 + 0.2
0.30000000000000004
More information about Python float and floating point arithmetic - here
The list comprehension is irrelevant, this is purely an issue with floating-point numbers. For an extremely detailed answer you should give this article a read: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Related
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 1 year ago.
I have been recently trying to make a calculator in python and added floating points in it
but unfortunately it gives me for this simple code
print(0.1 + 0.2)
out put
0.30000004
I have searched a lot for it in stackoverflow but I keep getting questions about why it happened and not how to fix it.
Edit:
a lot of people have been recently giving me private feedbacks about this already exists I appreciate that to improve stackoverflow but there are no questions most of them are explanations about why it is happening and not how to fix it. some of the feedbacks have got even questions that are not python
you can try any of the follow methods which is conventional for you
#for two decimal places use 2f, for 3 use 3f
val = 0.1 + 0.2
print(f"val = {val:.2f}")
#output | val = 0.30
#or else
print(round(val,2))
#output | val = 0.30
You can use the decimal built-in module with strings and make your own methods:
from decimal import Decimal
def exact_add(*nbs):
return float(sum([Decimal(str(nb)) for nb in nbs]))
exact_add(0.1, 0.2)
# > 0.3
I think the recommended way to resolve this is to determine a number of decimal places you want to consider and round to that using the built-in round function. Say you want to use 5 decimal places, you could do:
ans = 0.1 + 0.2
print(ans) # 0.30000004
round(ans,5)
print(ans) # 0.3
Note that round also gets rid of extra zeroes in the end. If you round 0.333333333333 to 5 decimals it will return 0.33333, but rounding 0.30000000004 returns 0.3.
This has nothing to do with python, but with the way floating point values are represented on your machine. The way floating point works is the same for all languages, and it can potentially introduce rounding errors. This link shows you exactly why you get this error.
Just reduce the number of visible digits and you'll be fine. Just now that all computers and calculators have limited space for numbers, and all of them are prone to rounding errors.
You can use:
a = 0.1 + 0.2
a = round(a, 2)
print(a)
Output: 0.3
use round() syntax to get rid of excessive number of zeros.
'''
a = 0.1
b = 0.2
c = a + b
answer = round(c,3) # here 3 represents the number of digits you want to round
print(answer)
'''
and incase you want more clarification on round() syntax just visit this link once: https://www.bitdegree.org/learn/python-round
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 4 years ago.
I would like to create an array of number equally spaced (0.1) between 0.1 and 100
step=0.1
range_a=numpy.arange(step,100+step,step)
why my first element is
range_a[0]
Out[27]: 0.10000000000000001
and not 0.1?
and how do I get an array equal to
[0.1, 0.2, 0.3, ..., 100]
As mentioned in the comments, this is due to how floats are handled. In general, floats are used for imprecise but quick calculations, and double is used where accuracy is important. Your code can be rewritten as follows to get precisely what you want
step = 0.1
range_a = numpy.arange(step, 100+step, step).astype(numpy.double)
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 6 years ago.
I am new to python and I tried this:
import numpy as np
x = np.arange(0.7,1.3,0.1)
print (x)
y = np.arange(0.6,1.3,0.1)
print (y)
The output was [ 0.7 0.8 0.9 1. 1.1 1.2 1.3] and [ 0.6 0.7 0.8 0.9 1. 1.1 1.2]. Why in the first case 1.3 appears in the list and in the second case it doesn't?
This is due to rounding errors. If you actually print the last element in x in it's full precision, you'll see that it is smaller than 1.3:
>>> import numpy as np
>>> x = np.arange(0.7,1.3,0.1)
>>> 1.3 > x[-1]
True
>>> x[-1]
1.2999999999999998
Note, as stated in the documentation
When using a non-integer step, such as 0.1, the results will often not be consistent. It is better to use linspace for these cases.:
arange is not suitable for floating point numbers:
When using a non-integer step, such as 0.1, the results will often not be consistent. It is better to use linspace for these cases.
I'm not familiar with the internals of numpy, but my guess is that this is a side effect of floating point numbers not being exact (meaning that they can't exactly represent some values).
See the numpy.arange documentation here:
specifically "When using a non-integer step, such as 0.1, the results will often not be consistent. It is better to use linspace for these cases"
I'm using the python2 math module to calculate sums with fsum. I understand that 0.1 usually can't be stored binary. As far as i understand math.fsum should fix this somehow.
import math
math.fsum([0.0, 0.1])
#0.1
math.fsum([0.1, 0.1])
#0.2
math.fsum([0.2, 0.1])
#0.30000000000000004
math.fsum([0.3, 0.1])
#0.4
math.fsum([0.4, 0.1])
#0.5
So math.fsum([0.2, 0.1]) == 0.3 will be False. Is this supposed to be like this? Am i doing something wrong?
How can i get 0.2 + 0.1 == 0.3 to be True?
You're misunderstanding what math.fsum does. It computes the most accurate possible sum of the given inputs (that is, the closest exactly representable value to the exact mathematical sum of the inputs). It does not magically replace its inputs with the numbers you originally thought of.
In your third line above, the input to math.fsum is a list containing the values 0.1000000000000000055511151231257827021181583404541015625 and 0.200000000000000011102230246251565404236316680908203125 (remember that with binary floating-point, What You See Is Not What You Get; here I'm showing the exact values that Python's using). The exact sum of those two values is 0.3000000000000000166533453693773481063544750213623046875, and the closest representable IEEE 754 binary64 float to that exact sum is 0.3000000000000000444089209850062616169452667236328125, which is what you're getting.
You're asking for math.fsum to behave as though it were given the exact values 0.1 and 0.2, but it has no way of knowing that that's what you want: it can only operate on the inputs that you give it.
Note that on most machines, addition of two floats will already be correctly rounded, so there's no advantage to using math.fsum. math.fsum is intended to remove the accumulation of rounding error involved in summing more than two floats.
Actually, you should avoid to use the equal operator for the float. because computer present them in binary, and only an approximate value of the float.
if you real need to check whether two float is equal, you need to define a tolerance:
For example:
def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
please refer to this:
What is the best way to compare floats for almost-equality in Python?
and I find this funny website:
http://0.30000000000000004.com/
this 0.1 + 0.2 not equals to 0.3 exits in most languages.
This question already has answers here:
Python rounding error with float numbers [duplicate]
(2 answers)
Python weird addition bug [duplicate]
(4 answers)
Closed 9 years ago.
I'm trying to add decimal numbers a decimal number and it works correctly but when I do 1.1 + 0.1 I get 1.2000000000000002 but all I want it to equal to is 1.2. When I do 1.0 + 0.1 I get 1.1 which is perfect but i don't get that for 1.1 + 0.1. So is there a way that I can get rid of the 000000000000002 from 1.2000000000000002?
Thanks.
As has been stated countless times, 0.1 cannot be represented exactly in IEEE 754 floating point. You can read all about why in What Every Computer Scientist Should Know About Floating-Point Arithmetic or The Floating Point Guide
You can trucate or round the value:
>>> round(1.1+.1,2)
1.2
>>> "%.*f" % (1, 1.1+.1 )
'1.2'
>>> s=str(1.1+.1)
>>> s[0:s.find('.')+2]
'1.2'
If you want exact representation of those values, consider using the Decimal module:
>>> import decimal
>>> decimal.Decimal('1.1')+decimal.Decimal('.1')
Decimal('1.2')
Note that you need to start with the string representation of your float, '0.1' since 0.1 is not exactly representable in binary in IEEE floating point:
>>> decimal.Decimal(.1)
Decimal('0.1000000000000000055511151231257827021181583404541015625')
To then get a string representation back after you calculate, you can use str:
>>> str(sum(map(decimal.Decimal,['.1','.1','.5','.5'])))
'1.2'
Another alternative is to use a rational number library such as Fractions:
>>> from fractions import Fraction as Fr
>>> Fr(11,10)+Fr(1,10)
Fraction(6, 5)
With that result, you will still need to round, truncate, or use an arbitrary precision arithmetic package to get an exact number (depending on the inputs...)
You can try string formatting, documentation here.
>>> "%0.2f" % float(1.1 + 0.1)
'1.20'
Or Even:
>>> "%0.1f" % float(1.1 + 0.1)
'1.2'
As to why, it is explicitly described on PEP 327 here.
This is the literal answer to your question:
float(str(1.1 + 0.1)[0:3])
If you're interested in the "why" of the problem then refer to the links provided in the question comments.