【问题标题】: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

【问题讨论】:

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

标签: c++ c math


【解决方案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 这样的表达式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-01
      • 2012-05-23
      • 1970-01-01
      • 2011-07-05
      • 2013-05-13
      • 1970-01-01
      • 2010-09-05
      相关资源
      最近更新 更多