1

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?

4
  • 4
    docs.python.org/2/tutorial/floatingpoint.html Commented May 14, 2013 at 19:21
  • @MartijnPieters: It's only a dup if you ignore the fact that the OP mistakenly thought the list comprehension was part of the problem. The question is whether future searchers/readers are likely to have the same mistaken impression. Commented May 14, 2013 at 19:43
  • Step 1 or 2 of trying to solve this question should be "try it without a list comprehension to see if the results hold", @abarnert, so I believe the duplicate proposal is correct. Commented May 14, 2013 at 19:46
  • 2
    @abarnert: The problem is still the floating point rounding error. Someone else thinking they have the same problem will find this question, then be pointed to the dupe question to see that floating point errors can occur without list comprehensions too. Which is the point. Commented May 14, 2013 at 19:50

3 Answers 3

4

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)

Sign up to request clarification or add additional context in comments.

7 Comments

Exactly - this has nothing to do with the list comprehension. (Well, I'm not sure I'd call python floats "accurate" to any specific precision without a clearer definition of "accurate".) You get the same imprecise result if you just directly evaluate 0.1 * 3.
"floats are accurate up to 9 places after the decimal" is wrong. For example, float(1<<64)+.1 == float(1<<64) is True—it's not even accurate to 1 place after the decimal.
Also, similarly, if you don't have some out-of-band way of knowing the scale you care about, you often need something like num1 - num2 < 1e-3 * max(num1, num2) (or gmean or some other function, depending on the case). And of course this only works for positive numbers, because you forgot the abs. I think it would be better to link to some discussion of epsilon thresholding or error analysis than to try to explain it in one line.
your right ... removed wrong part ... I coulda sworn I read somewhere that python guaranteed floats up to X precision ... but meh
@JoranBeasley: Up to X precision means the number of significant digits, not the number of fractional digits. Also, Python's docs speak a bit loosely: if you take subnormals into account, the number of significant digits in an IEEE double can be less than 1.
|
2

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

Comments

1

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.