棘手的算术还是花招?

Posted

技术标签:

【中文标题】棘手的算术还是花招?【英文标题】:Tricky arithmetic or sleight of hand? 【发布时间】:2010-08-01 05:09:21 【问题描述】:

Vincent 通过建议这个函数回答了Fast Arc Cos algorithm。

float arccos(float x) 
 
    x = 1 - (x + 1); 
    return pi * x / 2; 
 

问题是,为什么是x = 1 - (x + 1) 而不是x = -x

【问题讨论】:

注意:显然这里提供的解决方案不太正确,但问题仍然存在。 【参考方案1】:

仅当 (x + 1) 导致精度损失时,它才会返回不同的结果,即 x 比 1 大或小多个数量级。

但我不认为这是棘手诡计,我认为这只是错误

cos(0) = 1 but f(1) = -pi/2
cos(pi/2) = 0 but f(0) = 0
cos(pi) = -1 but f(-1) = pi/2

其中f(x) 是Vincent 的arccos 实现。它们都偏离pi/2,至少这三个点正确的线性近似是

g(x) = (1 - x) * pi / 2

【讨论】:

我仍然没有得到精度部分的损失,你能提供一个例子吗? @David,试试1.0 - (1.0 + 1e-16) vs -(1e-16) 看一下acos 的图表 - 更好的线性近似值(基于 x=0 处的切线)将是 g(x) = pi/2 - x,它非常准确,除非 x 接近-1 或 1 @BlueRaja:我同意简单地连接这三个点并不是最优的(使用 x=0 处的切线也不能最小化均方误差),只是它是最简单的近似这可能有用。文森特给的原件肯定没用。【参考方案2】:

我不会立即看到细节,但想想当 x 从任一侧接近 1 或 -1 时会发生什么,并考虑舍入误差。

【讨论】:

【参考方案3】:

加法会导致两个数字都被归一化(在这种情况下,与 x 相关)。 IIRC,在 Knuth 的第 2 卷关于浮点运算的章节中,您甚至可以看到像 x+0 这样的表达式。

【讨论】:

以上是关于棘手的算术还是花招?的主要内容,如果未能解决你的问题,请参考以下文章

我们如何比较算术运算的结果是 NaN 还是无穷大..?

QlikSense - 集合分析 - 处理复杂性 - 算术,字段,变量,变量内的变量,大于等

关于C++算术类型

2017.031.数字电路与系统-算术逻辑单元

76.算术运算符

算术移位和逻辑移位实现分析