psychopy.org | Reference | Downloads | Github

Not loading negative values


#1

hi all, i’m having a problem with the IF command loading negative values, here is an example of my code:

           if line_pos_int==-0.05:
                threshold_int=29
            elif line_pos_int==0.01:
                threshold_int=35
            elif line_pos_int==0.05:
                threshold_int=41

now if I print my two variables (line_pos_int and threshold_int), I get something like:

line_pos_int=0.01
threshold_int=35
line_pos_int=0.05
threshold_int=41
line_pos_int=-0.05
threshold_int=41
line_pos_int=0.01
threshold_int=35

any thoughts?
thanks!
Laurel


#2

Computers can precisely store integers (i.e. they are very good at counting), but they can only approximate floating point numbers. e.g. this may or may not happen, depending on what way the wind is blowing:

>>> a = 1/20
>>> b = 0.05
>>> a == b
False

This problem is in no way restricted to Python, but is a general computing issue. You should change your code so that you never directly compare floating point values for equality. e.g. find a way to express your comparisons using proxy values (like integers), or subtract one floating point value from the other and see if the result is acceptably close to zero. For example:

# do floating point arithmetic within some error tolerance:
 if line_pos_int + 0.05 <= 0.0000001:
    threshold_int = 29
# etc

or:

# convert floating point to integer comparisons (not
# always practical):
if int(line_pos_int * 100) = -5:
    threshold_int = 29
# etc

#3

That is very interesting! Thank you! I tried addition which didnt work but multiplication did. Thank you for your multiple examples!.

This didnt work:

            if line_pos_int+1.7==1: #-0.3
                threshold_int=3
            elif line_pos_int+1.75==1: #-0.25:
                threshold_int=7
            elif line_pos_int+1.8==1:#-0.2:
                threshold_int=12
            elif line_pos_int+1.85==1:#-0.15:
                threshold_int=18
            elif line_pos_int+1.9==1:#-0.1:
                threshold_int=24
            elif line_pos_int+1.95==1:#-0.05:
                threshold_int=29
            elif line_pos_int+1==1: #0:
                threshold_int=35

This did work:

            if int(line_pos_int*100)==-30: #-0.3
                threshold_int=3
            elif int(line_pos_int*100)==-25: #-0.25:
                threshold_int=7
            elif int(line_pos_int*100)==-20:#-0.2:
                threshold_int=12
            elif int(line_pos_int*100)==-15:#-0.15:
                threshold_int=18
            elif int(line_pos_int*100)==-10:#-0.1:
                threshold_int=24
            elif int(line_pos_int*100)==-5:#-0.05:
                threshold_int=29
            elif int(line_pos_int*100)==0: #0:
                threshold_int=35

#4

That is because you are still dealing with floating point numbers in that example. e.g. 0.3 + 1.7 = 2.0 The floating point number 2.0 is not necessarily precisely equal to the integer 2. So the example above was to show that if we want to compare two integers for equality, you need to subtract one from the other and check to see if the answer is acceptably close to 0 (e.g. <= 0.000000001).

With integers, 2-2 gives a result of exactly 0, as you would expect. With floating point variables, the values are approximations so 2.0 - 2.0 might not yield 0 exactly and so we have to compare the difference within some tolerance.


#5

I’m glad that the issue is already solved but here is another important piece to the problem:
If you divide an integer by an integer, the result is returned as an integer in Python 2. Therefore, 1/20 == 0. And consequently, 1/20 != 0.05.
In order to receive a float value, at least one element of the division needs to be a float. Hence, 1/20.0 == 0.05 is TRUE (please note the “.0” after the 20 in order to obtain a float).


#6

Hi, just as a supplement to what @mario.reutter says, it is generally true in Python 2 that 1/20 == 0 , but not in Python 3, where 1/20 == 0.05. To insulate against this:

(1) All Builder experiments include this line at the beginning, to mimic the integer division behaviour of Python 3:

from __future__ import division

This means that 1/20 == 0.05 within Builder code even though it is currently based on Python 2.7.

(2) PsychoPy is being migrated to Python 3, so you should get used this behaviour in the (hopefully near) future, even in your non-Builder-generated code.