Why is sin(180) not zero when using python and num

2019-01-24 03:42发布

问题:

Does anyone know why the below doesn't equal 0?

import numpy as np
np.sin(np.radians(180))

or:

np.sin(np.pi)

When I enter it into python it gives me 1.22e-16.

回答1:

The number π cannot be represented exactly as a floating-point number. So, np.radians(180) doesn't give you π, it gives you 3.1415926535897931.

And sin(3.1415926535897931) is in fact something like 1.22e-16.

So, how do you deal with this?

You have to work out, or at least guess at, appropriate absolute and/or relative error bounds, and then instead of x == y, you write:

abs(y - x) < abs_bounds and abs(y-x) < rel_bounds * y

(This also means that you have to organize your computation so that the relative error is larger relative to y than to x. In your case, because y is the constant 0, that's trivial—just do it backward.)

Numpy provides a function that does this for you across a whole array, allclose:

np.allclose(x, y, rel_bounds, abs_bounds)

(This actually checks abs(y - x) < abs_ bounds + rel_bounds * y), but that's almost always sufficient, and you can easily reorganize your code when it's not.)

In your case:

np.allclose(0, np.sin(np.radians(180)), rel_bounds, abs_bounds)

So, how do you know what the right bounds are? There's no way to teach you enough error analysis in an SO answer. Propagation of uncertainty at Wikipedia gives a high-level overview. If you really have no clue, you can use the defaults, which are 1e-5 relative and 1e-8 absolute.



回答2:

The problem it is not a rounding error of pi. Note that the problem do not appear for cosine:

    In [2]: np.sin(np.pi)
    Out[2]: 1.2246467991473532e-16  != 0.
    In [3]: np.cos(np.pi)
    Out[3]: -1.0                    == -1.

The problem is much more ... complicated. It is related with the precision of pi inside the processor. This was discovered and explained here: https://randomascii.wordpress.com/2014/10/09/intel-underestimates-error-bounds-by-1-3-quintillion/



标签: python numpy sin