Value of sine 180 is coming out as 1.22465e-16
Just to be clear, your program is giving you the correct answer. That is to say, it is doing exactly what you told it to do in your code.
180*M_PI
is correctly rounded (per IEEE-754), and gives the value:
565.4866776461627750904881395399570465087890625
dividing that by 180 is also correctly rounded, and gives the result:
3.141592653589793115997963468544185161590576171875
which is not exactly the mathematical value of π. In fact, it is:
π - 0.0000000000000001224646799147...
the first order term of the Taylor series for sin(x)
around π is (π-x), so sin(π - x)
is, for small x
, nearly exactly -x
. In fact, the result that you're getting is the correctly rounded result. The library couldn't possibly deliver a more accurate answer.
As Ben Voigt suggested, if this is actually a problem for you, you can work around it by reducing the argument into the range [-90, 90) before converting from degrees to radians. An even better suggestion is njuffa's to use a sinpi
function that will do this work for you. iOS does not have such a function, but it does have vvsinpi
, which implements sin(π*x) for vectors, and can be made to do what you want:
double result;
int vectorLength = 1;
vvsinpi(&result, &operand, &vectorLength);
Please also file a bug requesting that sinpi
be added to the math library as an extension.
This is caused by the inability of a binary number system to exactly represent PI.
One possible solution would be to use the symmetry of sin:
sindeg(x) = sindeg(180 - x)
(or alternatively):
sin(x) = sin(M_PI - x)
Transforming the angle into the range (-pi/2 : pi/2) reduces the error of the approximation.
Basically:
if([operation isEqual:@"sin"]){
operand = fmod(operand, 360);
if (operand > 270) operand -= 360;
else if (operand > 90) operand = 180 - operand;
operand=sin(operand*M_PI/180.0);
}
You might want to check whether the math library on this platform offers the function sinpi() as an extension to the C/C++ standard math library functions. This would avoid explicit multiplication with the approximate value of pi (i.e. M_PI) and give you improved accuracy.
operand = sinpi (operand / 180.0)