Why is sin(180) not zero when using python and numpy?
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.
Faced same problem,
import numpy as npprint(np.cos(math.radians(90)))>> 6.123233995736766e-17
and tried this,
print(np.around(np.cos(math.radians(90)), decimals=5))>> 0
Worked in my case. I set decimal 5 not lose too many information. As you can think of round function get rid of after 5 digit values.
One solution is to switch to sympy when calculating sin's and cos's, then to switch back to numpy using sp.N(...) function:
>>> # Numpy not exactly zero>>> import numpy as np>>> value = np.cos(np.pi/2)6.123233995736766e-17# Sympy workaround>>> import sympy as sp>>> def scos(x): return sp.N(sp.cos(x))>>> def ssin(x): return sp.N(sp.sin(x))>>> value = scos(sp.pi/2)0
just remember to use sp.pi instead of sp.np when using scos and ssin functions.