0

I wonder why this statement is evaluated false:

>>> from numpy import sin,cos,pi
>>> sin(pi/4)==cos(pi/4)
False

in fact sine and cosine of pi/4 should be √ 2 / 2. What's happen? And how to avoid this problem?

G M
  • 20,759
  • 10
  • 81
  • 84
  • 1
    Never compare float values on equality. At least use an epsilon. Calculations are never perfectly exact, because you have a limited precision. – honk Mar 16 '14 at 16:57
  • Floating point (Esp. irrational) values can never be accurately expressed.. Print them out individually and check. – UltraInstinct Mar 16 '14 at 16:57
  • 1
    Probably just floating point arithmetics, when I do `numpy.allclose(sin(pi/4), cos(pi/4))` I get `True`. – Akavall Mar 16 '14 at 16:57
  • 1
    @Thrustmaster: floating-point numbers are exactly what floating-point representations CAN represent accurately. Perhaps you meant to write *real values*. There is a lot of evidence here on SO that people get easily confused and puzzled about floating-point arithmetic and inaccurate statements such as your comment just add to the confusion. – High Performance Mark Mar 16 '14 at 17:04
  • @HighPerformanceMark Yup, you are correct. I actually meant "real numbers". :) – UltraInstinct Mar 16 '14 at 17:06
  • 1
    Since "pi/4" can't have an exact floating point representation and cos("pi/4")^2 > 0.5, it only makes sense, that sin("pi/4")^2 < 0.5, since the sum should equal to 1.0 as closely as possible. – Aki Suihkonen Mar 18 '14 at 13:36
  • 1
    This question is substantially different from the other one. – SamB May 01 '23 at 15:45
  • 1
    Yeah, I wouldn't say this question is a duplicate of https://stackoverflow.com/questions/588004/is-floating-point-math-broken merely cause they both are about the quirkyness of floating point math – Drkawashima May 01 '23 at 20:31
  • Thanks for your support @SamB it was nine years I was waiting for this moment. – G M May 03 '23 at 16:01

2 Answers2

4

If you look at what the results actually are:

>>> sin(pi/4)
0.70710678118654746
>>> cos(pi/4)
0.70710678118654757

You will note that they are very, very close, but not exactly the same. Due to these kinds of floating point representation issues, it is usual to use a threshold to compare values that should be the same:

>>> abs(sin(pi/4) - cos(pi/4)) < 1e-9
True

Fun fact: using numpy's sqrt, too:

>>> sqrt(2)/2
0.70710678118654757
>>> sqrt(2)/2 == cos(pi/4)
True
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • thanks seems sin(pi/4) is not evaluate as sqrt(2)/2... – G M Mar 16 '14 at 17:03
  • 2
    @GM - Most likely, cos(pi/4) also isn't. In fact, your pi/4 isn't pi/4, exactly. pi is an irrational number. It cannot be represented exactly. – David Hammen Mar 16 '14 at 19:34
2

Because floating point representation isn't always exact and functions like cos and sin are calculated by approximate numerical methods, it is unreasonable to imagine that the results will be bitwise identical. On my machine, I get this when I compare sine and cosine

>import numpy
>x=numpy.sin(numpy.pi/4)
>y=numpy.cos(numpy.pi/4)
>print numpy.abs(x-y)/numpy.max(x,y)
1.57009245868e-16

ie. the relative error is very close to the IEEE 754 double precision epsilon. If you need to compare two floating point values, compare a delta value to a tolerance, or use numpy.allclose()

talonmies
  • 70,661
  • 34
  • 192
  • 269