正弦180的值为1.22465e-16

sre*_*sad 3 floating-point ios4

我想在ios4中实现一个正弦和余弦计算器:

if([operation isEqual:@"sin"]){
    operand = (operand*M_PI/180.0);
    operand=sin(operand);
}
Run Code Online (Sandbox Code Playgroud)

代码为我提供了从0到90的正确答案.

当我给出180的价值时,我会得到1.22465e-16答案.我期待零.

这个小差异来自哪里?

Ste*_*non 7

为了清楚起见,您的程序正在给您正确的答案.也就是说,它正在完成你在代码中告诉它要做的事情.

180*M_PI 正确舍入(根据IEEE-754),并给出值:

565.4866776461627750904881395399570465087890625
Run Code Online (Sandbox Code Playgroud)

除以180也正确舍入,并给出结果:

3.141592653589793115997963468544185161590576171875
Run Code Online (Sandbox Code Playgroud)

这不完全是π的数学值.实际上,它是:

? - 0.0000000000000001224646799147...
Run Code Online (Sandbox Code Playgroud)

sin(x)大约π 的泰勒级数的一阶项是(π-x)sin(? - x),对于小的x,几乎是精确的-x.事实上,你得到的结果是正确的舍入结果.图书馆无法提供更准确的答案.

正如Ben Voigt所建议的那样,如果这实际上是一个问题,你可以通过在将度数转换为弧度之前将参数减少到[-90,90]范围来解决它.更好的建议是njuffa使用一个sinpi能够为你完成这项工作的功能.iOS没有这样的功能,但确实有vvsinpi,它实现了矢量的sin(π*x),并且可以做你想做的事情:

double result;
int vectorLength = 1;
vvsinpi(&result, &operand, &vectorLength);
Run Code Online (Sandbox Code Playgroud)

还请提交一个错误请求将sinpi其作为扩展名添加到数学库中.

  • `__sinpi()`自iOS 7和OS X 10.9开始提供. (2认同)

Ben*_*igt 5

这是由二进制数系统无法准确表示PI引起的.

一种可能的解决方案是使用sin的对称性:

sindeg(x) = sindeg(180 - x)
Run Code Online (Sandbox Code Playgroud)

(或者):

sin(x) = sin(M_PI - x)
Run Code Online (Sandbox Code Playgroud)

将角度转换为范围(-pi/2:pi/2)可减少近似误差.

基本上:

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);
}
Run Code Online (Sandbox Code Playgroud)