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)