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

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.