5

Possible Duplicate:
Why can't decimal numbers be represented exactly in binary?
Program not entering if statement

So I'm trying to run a program that has two variables, when one variable is equal to another, it performs a function. In this case, printing spam. However, for some reason, when I run this program, I'm not getting any output even though I know they are equal.

g=0.0
b=3.0

while g < 30.0:
    if g==b:
        print "Hi"
    g+=.1
    print g, b
Community
  • 1
  • 1
user1541756
  • 153
  • 1
  • 1
  • 7

3 Answers3

9

You are assuming that adding .1 enough times to 0.0 will produce 3.0. These are floating point numbers, they are inaccurate. Rounding errors make it so that the value is never exactly equal to 3.0. You should almost never use == to test floating point numbers.

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
6

A good way to do this is to count with integer values (e.g., loop with i from 0 to 300 by 1) and scale the counter only when the float value is used (e.g., set f = i * .1). When you do this, the loop counter is always exact, so you get exactly the iterations you want, and there is only one floating-point rounding, which does not accumulate from iteration to iteration.

The loop counter is most commonly an integer type, so that addition is easily seen to be exact (until overflow is reached). However, the loop counter may also be a floating-point type, provided you are sure that the values and operations for it are exact. (The common 32-bit floating-point format represents integers exactly from -224 to +224. Outside that, it does not have the precision to represent integers exactly. It does not represent .1 exactly, so you cannot count with increments of .1. But you could count with increments of .5, .25, .375, or other small multiples of moderate powers of two, which are represented exactly.)

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
0

To expand on Karoly Horvath's comment, what you can do to test near-equality is choose some value (let's call it epsilon) that is very, very small relative to the minimum increment. Let's say epsilon is 1.0 * 10^-6, five orders of magnitude smaller than your increment. (It should probably be based on the average rounding error of your floating point representation, but that varies, and this is simply an example).

What you then do is check if g and b are less than epsilon different - if they are close enough that they are practically equal, the difference between practically and actually being the rounding error, which you're approximating with epsilon.

Check for

abs(g - b) < epsilon

and you'll have your almost-but-not-quite equality check, which should be good enough for most purposes.

algorowara
  • 1,700
  • 1
  • 15
  • 15