为什么Spotlight给`cos(pi / 2)`赋了错误的值?


8

如您所知,Spotlight可以完成简单的数学运算。例如,如您所料,键入cos(pi)将导致-1。我刚刚输入cos(pi/2),应该为0,但这给了我-5e-12

是的,这可能是由于舍入错误造成的,但是请继续:cos(pi/2)!我认为,这显然像是bug。你怎么看?


1
cos(x)是一个超越函数。除非它们对pi,pi / 2等的值进行硬编码,否则应该会出现一些错误。
纳文2014年

@Navin实际上,我确实希望它们对这些值进行硬编码,因为它们非常重要。
poitroae

1
pi本身将被硬编码(当您获得-1时cos(pi)),但是一旦您对其进行操作,您将获得一个浮点数,其精度有限。OSX没有硬编码pi/2pi/4等等,它实际上操作。
哈里格2014年

2
@harryg尽管有四舍五入的错误可以通过切换到十进制来解决,但这不是其中之一。如果要0.1精确表示,则十进制很有用。精确地,但是对于不能以二进制或十进制精确表示的pi这样的无理数没有用。
CodesInChaos 2014年

1
作为参考,在Ruby中:irb(main):009:0> Math.cos(Math::PI/2) => 6.123233995736766e-17
harryg 2014年

Answers:


13

这是由于pi的精度不足以及内置系统整体上都缺乏精度所致。

pi = 3.1415926536

pi/2 = 1.5707963268 

cos(1.5707963268) = -5.103412e-12

FYI =  5.103412e-12 = 0.000000000005103412 ~ 0 


关于整体系统精度:

3.141592653589793238462643383 = 3.1415926536 

在Python中,我们得到以下信息:

>>> float("3.141592653589793238462643383")
3.141592653589793

如我们所见,由于精度甚至与float表示形式都不匹配,因此精度存在问题。


这是由于缺乏精度,但是不能将如此大的误差归咎于浮点数。
丹尼斯·贾黑鲁丁

2
pi值可能更缺乏精度。
Matthieu Riegler 2014年

5

它们没有以异常的浮点精度存储π。他们为π使用了不正确的值,具有双精度。为了近似二进制数3.1415926536,至少需要38位:

3.14159265359922… > 11.001001000011111101101010100010001001

请注意,2 ^ -36约为1.5e-11,与结尾的99一致。 双精度浮点的有效位数为52位。要评估cos(pi/2)为-5e-12,唯一可能的选择是48位类型,这很奇怪。

在0和π附近(导数几乎为零),无法非常精确地计算cos(θ):

cos(3.1415926536) ≈ -0.999999999999999999999947911

与-1的差约为5.2e-23,小于的ε double,因此cos(3.1415926536)计算为正好为 -1 ...,这是不正确的。

接近±π/ 2时,导数[ -sin(θ) ]接近±1,因此输入端的误差变为输出端的误差。

cos(1.57079632679961) ≈ -4.71338076867830836e-12
cos(1.57079632679962) ≈ -4.72338076867830836e-12
cos(1.57079632680000) ≈ -5.10338076867830836e-12

我碰巧有一个TI计算器,显示的位数减少了一位,并计算cos(π/2)为-5.2e-12。但是,它在电子上有很大的不同,旨在提供的准确值cos(90°)

我猜想在Spotlight中,cos(pi/2)是通过获取π的值,转换为十进制字符串,将其存储为(精确,有理)二进制值11.00100100001111110110101010001000100100001101101111(或10000),然后除以2,然后从中减去π/ 2 的真实值。您应该找出是否cos(pi/2 + cos(pi/2))接近零(可能是-2.2e-35)。

乘以2的幂只会影响指数,而不影响有效位数。通过重复减半或加倍,可以确定如何应用舍入。


没有什么与降价- MathJax仅在数学相关站点启用,不是SE-宽。
grg

1
cos(pi / 2 + cos(pi / 2))精确显示为0。
Nick Matteo 2014年

4

这是一个在10.9.2上可重现的错误-像这样的浮点舍入错误是非常典型的。

如果我不得不猜测的话,pi的值将被处理得不够精确。

  • cos(999999 * pi)没有错误
  • cos((999999 + 1)* pi)确实有错误-可能取整

如果您想查看Apple的错误修复工具,我将前往https://developer.apple.com/bug-reporting/


5
真的是错误吗?这种操作的精度应该是多少?
爱德华2014年

我不是注册开发人员,但是如果您能为我们提交它,我将不胜感激!
poitroae 2014年

4
@Édouard 如果导致用户期望符号数学具有某些功能,则可以将其视为错误。任何计算机代数系统(CAS)当然都会知道cos(π/ 2)= 0!另一方面,指望Spotlight包含CAS几乎是不合理的。并且在浮点算法领域中,可以期望得到像OP报告这样的结果。也许任何错误报告都可以更好地标记为功能请求。
Harald Hanche-Olsen 2014年

1
@Édouardbmike实际上是正确的,这是一个错误,而不仅仅是舍入错误。给定标准双精度算法,这种操作的预期精度约为10 ^ -16,而不是10 ^ -12。您可以自己尝试用自己喜欢的语言编写程序,该程序可以利用CPU的浮点支持,进行计算并检查结果的位模式。正如bmike所说,可能的原因是Spotlight使用的π值的定义不够精确。
Szabolcs 2014年

2
这里发生了一些奇怪的事情。 cos(2*acos(0)*0.5)返回多个订单10^-10。并不是因为π常数不够精确。我无法解释这个结果:对于双精度来说太不精确了,对于单精度来说太精确了。
Szabolcs 2014年

4

从其他答案和评论中,以下内容变得清楚:

即使得到完美的软件实现,您得到非零结果的事实也不是错误,这会遇到浮点计算的限制。但是,大约10 ^ -12的误差确实很大。

这不应该归咎于浮点数的不准确性。您得到的结果是这样的:

cos(1.5707963268)

可以使用任何替代软件包来验证。如果您要cos(pi/2)使用其中一个软件包进行评估,则肯定会比10 ^ -12接近零。

总之,我看到两个可能的限制,其中之一必须适用:

  1. Pi的存储精度不足,或者至少pi / 2导致精度不足
  2. Cos仅仅将精度不足作为输入

也许具有软件访问权限的人可以验证其中哪些适用。

更新 如评论中所述,问题似乎在于常量的准确性pi


真奇怪 1.5707963268是Spotlight在计算pi / 2时提供的结果。经过几次简单的尝试,Spotlight似乎为1以下的数字显示10位有效数字,为1以上的数字显示11位。但是出于什么奇怪的实现原因,将在计算内部而不是之后进行舍入步骤?
爱德华2014年

1
我还想指出,如果您为Spotlight提供更精确的近似pi / 2(例如,通过复制粘贴Wolfram Alpha中的10位以上的数字),则精度会提高。
爱德华2014年

感谢您确认我的猜测,即pi的精度是OP问题中0到大约10 ^ -12之间的错误的原因。
bmike

您多久看到一次这样的情况:“ 10 ^ -12确实很大”
GEdgar 2014年

2

考虑到这-5e-12是一个很小的数字,这一个舍入误差。

我认为这是聚光灯显示的小数位数比pi用于计算trig函数的常量或无穷级数定义中使用的位数多的结果。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.