1

Straight to the chase I want to create a function which calculates the length of a step.

This is what I have:

def humanstep(angle):
    global human
    human[1]+=math.sin(math.radians(angle))*0.06
    human[2]+=math.cos(math.radians(angle))*0.06

So if the angle is 90 then the x value (human[1]) should equal 0.06 and the y value equal to 0.

Instead the conversion between radians and degrees is not quite perfect and these values are returned.

[5.99999999999999, 3.6739403974420643e-16]

Is there anyway to fix this?

Lossy
  • 142
  • 1
  • 5

7 Answers7

5

This is representation error due to how floating point arithmetic works. See the following page from the Python documentation: Floating Point Arithmetic: Issues and Limitations.

FTA:

Note that this is in the very nature of binary floating-point: this is not a bug in Python, and it is not a bug in your code either. You’ll see the same kind of thing in all languages that support your hardware’s floating-point arithmetic (although some languages may not display the difference by default, or in all output modes).

For further reading, see the following pages:

alanc
  • 4,102
  • 21
  • 24
Donut
  • 110,061
  • 20
  • 134
  • 146
1

Exactly how accurate do you want? The above is accurate to 15dp.

dan_waterworth
  • 6,261
  • 1
  • 30
  • 41
1

If you want accurate results, you are doing it correctly.

If you want mathematically exact results like [6, 0], use a symbolic math library such as sympy

Notice that these are very different goals.

Lee
  • 29,398
  • 28
  • 117
  • 170
Christian Oudard
  • 48,140
  • 25
  • 66
  • 69
0

You should read up on floating-point numbers, as these calculations are naturally imperfect and some numbers cannot be represented accurately using Python's floating point numbers. (Obviously, a fixed number of bits cannot represent the infinitely many real numbers.

The short answer is no. You can round if you want.

erjiang
  • 44,417
  • 10
  • 64
  • 100
0

As the others have said, it's floating point error. You can use the Decimal module, which can give you arbitrary precision math

Falmarri
  • 47,727
  • 41
  • 151
  • 191
  • 2
    Unless you have infinite RAM and CPU speed, the Decimal module will still suffer from all the usual limitations of floating-point math. – Marcelo Cantos Dec 13 '10 at 17:29
0

If you want to avoid the representation issues inherent in floating-point numbers, you can use a Decimal, but you will need to implement your own trigonometric functions. This will get you arbitrary precision but it will be rather slow.

kindall
  • 178,883
  • 35
  • 278
  • 309
0

As everyone has said, this is to do with binary representation issues - 0.06 is not a "round" figure in binary (just like 1/3 is not in decimal). It has nothing to do with the trig functions. If you drop them out and just do:

human[1]+=0.06
human[2]+=0.0

and look at the results you will see the same.

However, in Python 2.7 up the representation of floating point numbers has been improved. It will now display the shortest decimal number that gives that binary number - in this case I think it would display the answer you expect (only running 2.5 here so I can't quickly test). See this article for more information.

neil
  • 3,387
  • 1
  • 14
  • 11