5

I have just started learning python and I have stumbled across a particularity

python version:

Python 2.7.2 (default, Jul 20 2011, 02:32:18) [GCC 4.2.1 (LLVM, Emscripten 1.5, Empythoned)] on linux2

on:http://repl.it/languages/Python

Working with the interpreter assigning:

    pi = 3.141 // 3 places decimal precision
    #typing pi  & pressing return puts 3.141
   type(pi)
=> <type 'float'>
    pi = 3.1415
   type(pi)
=> <type 'float'>
    #pi puts 3.1415000000000002

Ok floating point precision is notorious for being unprecise; but why do only the 4 point precision get that "tail"?

Also:

 pi2 = 3.1415100000000002
 pi == pi2 # pi was assigned 3.1415
 => True
 print(pi2)
 3.14151 # Where's my precision? 
raam86
  • 6,785
  • 2
  • 31
  • 46
  • 1
    Not every decimal fraction can be precisely represented by a binary encoded float. For this reason, using `==` with floats is generally not a good idea. A much simpler case: `0.1 + 0.2` evaluates to `0.30000000000000004`. This is not loss of precision, this is a byproduct of encoding a decimal fraction in binary IEEE-754 format. – Alexei Sholik Jul 17 '13 at 09:52
  • @android why does it cut my precise assignment? – raam86 Jul 17 '13 at 09:53
  • If you want your precision, you can use `Decimal` module. – zhangyangyu Jul 17 '13 at 09:56
  • @raam86 http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems. [This](http://docs.python.org/2/library/decimal.html) might help. – Alexei Sholik Jul 17 '13 at 09:56
  • @raam86 If you're still confused, read up on how to convert a fraction from decimal to binary and try doing this conversion by hand (on paper) for `0.1`. You'll see why. – Alexei Sholik Jul 17 '13 at 09:58
  • @Zhenya I have actually searched a lot for it but didn't find something exactly like this, not python related anyway – raam86 Jul 17 '13 at 10:21
  • This is by no means python-specific. I guess for any language X there are several questions about the floating-point. Python-related (first or second google hit): http://stackoverflow.com/questions/1594985/why-do-simple-math-operations-on-floating-point-return-unexpected-inacurate-re and many more. – ev-br Jul 17 '13 at 10:23

1 Answers1

4

Integers and floats are given a certain number of bits. For integers, each bit corresponds to a power of two. The first digit is 20, then 21, 22, and so on. So to store the integer 5 we have 20 + 22 = 1 + 4.

For floating point numbers, we store them in two parts. The exponent, and the decimal. If we have an decimal of .75 and a exponent of 2, we do .75 * 102 = 7.5. The decimal is stored as negative powers of 2. So we have 2-1, 2-2. 2-3. etc. These equate to .5, .25, .125, etc.

Some numbers are impossible to store, because they literally require infinite bits to represent, like 0.1, and others like 3.1415 require more bits than the CPU provides for floating-point numbers (24 is standard for 32bit floats, but algorithms vary).

The correct way to compare floats is to have a variance defined, and use something along these lines.

variance = .0001
floatsEqual = lambda f1, f2: f1 - variance <= f2 and f1 + variance >= f2

if (floatsEqual(3.1415, 3.1415 + 1 - 1)):
    pass

In Python, the decimal library is also useful.

Brigand
  • 84,529
  • 20
  • 165
  • 173