1

Could you please help me with this problem?

Code:-

import numpy as np

def test(numList):
    yesList=[]
    for num in numList:
        print num, "start here"
        for i in np.arange(2.0,3.0,0.1):
            print i
        if num==i: yesList.append(num)
    return yesList

print test([2.1,2.3,3.0])

Output:-

2.1 start here
2.0
2.1
2.2
2.3
2.4
2.5
2.6
2.7
2.8
2.9
2.3 start here
2.0
2.1
2.2
2.3
2.4
2.5
2.6
2.7
2.8
2.9
3.0 start here
2.0
2.1
2.2
2.3
2.4
2.5
2.6
2.7
2.8
2.9
[2.1]

I want it to print [2.1,2.3] but it just gives me [2.1] as shown.

Gabe
  • 84,912
  • 12
  • 139
  • 238
user1594450
  • 11
  • 1
  • 2
  • It seems like you've identified the problem already in your tag - floating-point. – irrelephant Aug 13 '12 at 05:56
  • Your formatting was initially incorrect (the function wouldn't compile), so I had to guess at what you meant based on your sample output. If I guessed wrong, please correct it. – Gabe Aug 13 '12 at 05:59

2 Answers2

3

The short answer is that you're using floating-point (inexact) numbers and expecting exact results, which will ultimately fail. The long answer is much more complicated, but for a start look at the first item in this site's floating-point FAQ: Is floating point math broken? (It's a JavaScript question, but it applies to all languages equally well.)

Cœur
  • 37,241
  • 25
  • 195
  • 267
Gabe
  • 84,912
  • 12
  • 139
  • 238
0

It also depends how loop variables are incremented in python... (i+1)-th value of loop could be either

  value[i] = startValue + i * increment

or

  value[i] = value[i-1] + increment

In floating point, these values will differ...
So if you want to deal with strict floating point equality, you'll have to know this kind of detail

Also, it's very hard to control when the loop will stop... The last value could well be (3.0-epsilon)

A first rule is to not use loops on floating point whatever the language
Use integers instead:

def test(numList):
    yesList=[]
    for num in numList:
        print num, "start here"
        for i in np.arange(20,30,1):
            print i*0.1
            if num==(i/10.0): yesList.append(num)
    return yesList

Also note that i*0.1 and i/10.0 might differ since the float 0.1 is not exactly 1/10...
So, if you write if num==(i*0.1) it won't work as you expect...
For example (23*0.1) == (23/10.0) is false, and while the last happens to be strictly equal to the float 2.3, they are both different from the mathematical fraction 23/10.

A second rule tells to not use strict equality on float, that's rarely what you think

def test(numList):
    yesList=[]
    for num in numList:
        print num, "start here"
        for i in np.arange(20,30,1):
            print i*0.1
            if abs(num-0.1*i) < 0.05 : yesList.append(num)
    return yesList

Please read "What Every Computer Scientist Should Know About Floating-Point Arithmetic." http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

aka.nice
  • 9,100
  • 1
  • 28
  • 40