-2

I am new to coding in Python and am having trouble with something VERY basic. I did a search on this site for numbers not being equal but only found something related to Java. I have a very simple question. Why does 2.2 = 2.2 but 2.4 != 2.4? Code is presented below and here is a screenshot of the output I get: https://drive.google.com/file/d/0Bz3Lwr6GHeMLR1Nwc2hJRkZWQ3M/view

import os
import numpy

Mmin = 2.1
Mmax = 6.5

Magnitude = numpy.arange(Mmin, Mmax, 0.10)
print Magnitude

x = Magnitude[1]
y = 2.2
print x
print y
print x == y

a = Magnitude[3]
b = 2.4
print a
print b
print a == b

1 Answers1

0

Any language that stores floating points will usually store them as IEEE 32 or 64 bit binaries, which are essentially base 2 scientific notation, and therefore will never be exactly "2.1" or "2.4". As such, be very wary of doing any "==" comparisons with floating points in your code. Even if the numbers start off equal, any math operation rounding could throw you off by one LSB, breaking your code.

In your example, a better way might be to use integers that are 10x the floating point values. Your code will probably be faster this way too. Convert to floating points when you need to give a result:

import os
import numpy

Mmin = 21
Mmax = 65

Magnitude = numpy.arange(Mmin, Mmax, 1)
print Magnitude

x = Magnitude[1]
y = 22
print x
print y
print x == y

a = Magnitude[3]
b = 24
print a
print b
print a == b

Here's some example code that shows it a little clearer. I'm using 1/9 which is something that can't be exactly expressed in base 2 or base 10 floating point notation:

x = 1.0/9.0

y = 0
for i in range(1,15):
    y += x
    z = i * x
    print 'y =',
    print '%.20f'%y,
    print '   z =',
    print '%.20f  '%z,
    print z == y

The output is this:

y = 0.11111111111111110494    z = 0.11111111111111110494   True
y = 0.22222222222222220989    z = 0.22222222222222220989   True
y = 0.33333333333333331483    z = 0.33333333333333331483   True
y = 0.44444444444444441977    z = 0.44444444444444441977   True
y = 0.55555555555555558023    z = 0.55555555555555558023   True
y = 0.66666666666666674068    z = 0.66666666666666662966   False
y = 0.77777777777777790114    z = 0.77777777777777767909   False
y = 0.88888888888888906159    z = 0.88888888888888883955   False
y = 1.00000000000000022204    z = 1.00000000000000000000   False
y = 1.11111111111111138250    z = 1.11111111111111116045   False
y = 1.22222222222222254295    z = 1.22222222222222209886   False
y = 1.33333333333333370341    z = 1.33333333333333325932   False
y = 1.44444444444444486386    z = 1.44444444444444441977   False
y = 1.55555555555555602432    z = 1.55555555555555535818   False
Fred S
  • 985
  • 4
  • 11
  • This is raising more questions that it answers! So I guess when I import data the data won't be exact either? Unless I multiply everything before importing it such that it doesn't have any decimal places? – Rory McCully Oct 27 '14 at 18:08
  • It depends on what you want to do with the data. It will be "exact enough" I think. 64 bit floating points hold a lot of precision. If you're importing data from a file, it will probably be a string when it comes in. What you do with it after that will determine what gets lost in the shuffle. – Fred S Oct 27 '14 at 18:15
  • If you're still having trouble, consider asking a new question that gives a bit more detail on what you're trying to do. – Fred S Oct 27 '14 at 18:29