Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python floating point [duplicate]

Tags:

python

Possible Duplicate:
Floating point equality in python

I have a small "issue" about my Python code (I use version 2.5 right now, in ika game engine). I currently script objects for my game, and i would like to know, if its safe to compare two floating point number This way:

I will make a short example of what I do currently.

Every objects has a speed, from 0-9, represented in floating points. For example

speed = 4.83
cord_x = 10.0
cord_y = 10.0

They have an AddMovement method. This sets an X,Y value, and represents the goal coordinates for the object.

target_x = 25.0
target_x = 26.75
movement = True # This represents if the object is moveing or not

Every frame, the Maximum speed equals to this value:

maximum_x_speed = abs(cord_x-target_x)
maximum_y_speed = abs(cord_y-target_y)

And the real speed will be:

# Get the real X speed in this frame
if maximum_x_speed < speed:
    real_x_speed = maximum_x_speed
else:
    real_x_speed = speed

# Get the real Y speed in this frame
if maximum_y_speed < speed:
    real_y_speed = maximum_y_speed
else:
    real_y_speed = speed

Now, based on this real_x_speed value, and real_y_speed value, i substract this value from the coordinates.

if target_x < cord_x:
    cord_x -= real_x_speed
elif target_x > cord_x:
    cord_x += real_x_speed
if target_y < cord_y:
    cord_y -= real_y_speed
elif target_y > cord_y:
    cord_y += real_y_speed

And at the end, i check for equality

if cord_x == target_x and cord_y == target_y:
    # Halt movement, reached goal
    movement = False

I had floating point errors in the past, with the 0.1 issue, and like... I fear, that this will cause some kind of error. Or this is logically impossible?

If i had grammar mistakes, sorry for them. english is not my native language... I would really appreciate some tips, if i should change this logic, or not.

like image 660
Szebasztián Pertity Avatar asked Oct 11 '12 12:10

Szebasztián Pertity


People also ask

What does .2f mean in Python?

A format of . 2f (note the f ) means to display the number with two digits after the decimal point. So the number 1 would display as 1.00 and the number 1.5555 would display as 1.56 . A program can also specify a field width character: x = 0.1.

Why are Python floats inaccurate?

The floating-point calculations are inaccurate because mainly the rationals are approximating that cannot be represented finitely in base 2 and in general they are approximating numbers which may not be representable in finitely many digits in any base.

Why is floating point inaccurate?

Floating-point decimal values generally do not have an exact binary representation. This is a side effect of how the CPU represents floating point data. For this reason, you may experience some loss of precision, and some floating-point operations may produce unexpected results.


2 Answers

No, this type of code is never a good idea.

There will be floating point errors that accumulate, making it very hard to track. You really should use an "epsilon" approach, i.e. consider the two values equal if the difference is smaller than some set constant, which is often called epsilon:

def floats_equal(x, y, epsilon = 1e-4):
  return abs(x - y) < epsilon

Of course you must tweak the epsilon value as required for your application, but a game where the values represent pixel-based locations shouldn't need too much precision.

Note that, as also pointed out in other answers, there is a smallest epsilon that will work on the machine, but often you are better off using an application-level epsilon, such as the one above. When interpolating things in 2D pixel space for presentational purposes, there's seldom any point in precision in on the order of 2.22044604925 * 10-16, which happens to be the value of sys.float_info.epsilon on my local system.

like image 87
unwind Avatar answered Oct 13 '22 12:10

unwind


It is usually better to do this this way:

EPSILON = 0.00001 # or whatever 

if abs(cord_x - target_x) < EPSILON and abs(cord_y - target_y) < EPSILON:
    # Halt movement, reached goal
    movement = False

Some people choose EPSILON to be:

import sys

sys.float_info.epsilon

Which is the difference between 1 and the least value greater than 1 that is representable as a float - here

like image 42
zenpoy Avatar answered Oct 13 '22 10:10

zenpoy