Unlike others, this is not an x87 coprocessor problem. Xcode uses SSE by default to calculate the default floating point (with the exception of long double arithmetic).
"Problem": when you write cosf(M_PI_2) , you are actually telling the cosf(M_PI_2) compiler (gcc or llvm-gcc or clang) to do the following:
- Locate the extension
M_PI_2 in <math.h> . According to the POSIX standard, it is a double-precision literal that translates to a correctly rounded ฯ / 2 value. - Complete converted double precision value to single precision.
- Call
cosf math library cosf with a single precision value.
Please note that during this process you are not working with the actual value of ฯ / 2. Instead, you work with this value, rounded to a number representing a floating point number. While cos (ฯ / 2) is zero, you are not telling the compiler to do this calculation. Instead, you tell the compiler to make cos (ฯ / 2 + tiny), where is the tiny difference between the rounded value (float)M_PI_2 and the (non-representable) exact value of ฯ / 2. If cos calculated without any error, the result of cos (ฯ / 2 + tiny) is approximately -tiny. If it returns zero , that will be an error.
edit: step-by-step expansion of calculations on Intel layout using the current Xcode compiler:
M_PI_2 defined as
1.57079632679489661923132169163975144
but itโs not really a double precision number. When the compiler converts it to a double precision value, it becomes exactly
1.5707963267948965579989817342720925807952880859375
This is the closest double precision number to ฯ / 2, but it differs from the actual mathematical value of ฯ / 2 by about 6.12 * 10 ^ (- 17).
Step (2) rounds this number to a single point, which changes the value to exactly
1.57079637050628662109375
This is approximately ฯ / 2 + 4.37 * 10 ^ (- 8). When we calculate the cosf this number, we get:
-0.00000004371138828673792886547744274139404296875
which is the almost exact value of the cosine estimated at this point:
-0.00000004371139000186241438857289400265215231661...
In fact, this is a properly rounded result; there is no value that calculation could return that would be more accurate. The only mistake here is that the calculation that you asked the compiler to do is different from the calculations that you thought you asked to do.