正弦 180 的值为 1.22465e-16
我想在 ios4 中实现一个正弦和余弦计算器:
if([operation isEqual:@"sin"]){
operand = (operand*M_PI/180.0);
operand=sin(operand);
}
该代码为我提供了从 0 到 90 的值的正确答案。
当我给出 180 的值时,我得到 1.22465e-16
作为答案。我预计为零。
这个微小的差异从何而来?
I want to implement a Sine and Cosine calculator in ios4:
if([operation isEqual:@"sin"]){
operand = (operand*M_PI/180.0);
operand=sin(operand);
}
The code gives me correct answer for values from 0 through 90.
When I give value of 180, I get 1.22465e-16
as an answer. I expect zero.
Where does this small difference come from?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
需要明确的是,您的程序正在为您提供正确答案。也就是说,它完全按照您在代码中告诉它的方式执行。
180*M_PI
正确舍入(根据 IEEE-754),并给出值:将其除以 180 也正确舍入,并给出结果:
这不完全正确π 的数学值。事实上,它是:
围绕 π 的
sin(x)
泰勒级数的一阶项是 (π-x),因此sin(π - x)
是,对于小的x
,几乎完全是-x
。事实上,您得到的结果是正确舍入的结果。图书馆不可能提供更准确的答案。正如 Ben Voigt 所建议的,如果这对您来说确实是一个问题,您可以通过在从度数转换为弧度之前将参数减小到范围 [-90, 90) 来解决它。更好的建议是 njuffa 使用
sinpi
函数来为您完成这项工作。 iOS 没有这样的函数,但它有vvsinpi
,它为向量实现了 sin(π*x),并且可以做你想做的事:另请提交一个错误,要求 < code>sinpi 作为扩展添加到数学库中。
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:dividing that by 180 is also correctly rounded, and gives the result:
which is not exactly the mathematical value of π. In fact, it is:
the first order term of the Taylor series for
sin(x)
around π is (π-x), sosin(π - x)
is, for smallx
, 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 havevvsinpi
, which implements sin(π*x) for vectors, and can be made to do what you want:Please also file a bug requesting that
sinpi
be added to the math library as an extension.这是由于二进制数系统无法准确表示 PI 造成的。
一种可能的解决方案是使用 sin 的对称性:(
或替代方案):
将角度转换为范围 (-pi/2 : pi/2) 可以减少近似误差。
基本上:
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:
(or alternatively):
Transforming the angle into the range (-pi/2 : pi/2) reduces the error of the approximation.
Basically:
您可能想检查该平台上的数学库是否提供函数 sinpi() 作为 C/C++ 标准数学库函数的扩展。这将避免与 pi 的近似值(即 M_PI)显式相乘,并提高准确性。
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.
您依赖于处理器中的浮点数据类型。通过(相当大的)更多努力,您可以实现任意精度的数据类型。查看 MPFR http://www.mpfr.org/sample.html 它包含函数的定义(如 sin)将提供更多的数字。
You rely on the floating point datatype in your processor. With (quite considerable) more effort you can implement an arbitrary precision datatype. Look at MPFR http://www.mpfr.org/sample.html it contains definition for functions (like sin) that will deliver a higher number of digits.