【问题标题】:Floating number calculation precision: division vs multiplication浮点数计算精度:除法与乘法
【发布时间】:2014-06-26 22:03:13
【问题描述】:

我遇到过这种矢量/标量除法实现:

public static Vector2 operator /(Vector2 value1, float divider)
{
    float factor = 1 / divider;
    value1.X *= factor;
    value1.Y *= factor;
    return value1;
}

我尝试通过简单的划分来实现它:

public static Vector2 operator /(Vector2 value1, float divider)
{
    return new Vector2(value1.X / divider, value1.Y / divider);
}

我尝试运行模拟,结果似乎略有不同。

这是提高计算精度的某种技巧吗?

【问题讨论】:

  • 有什么不同的结果?
  • 结果不会被正确四舍五入,但通常保存除法的加速比结果精度损失更重要。 (如果你使用这个技巧,结果会更糟,而不是更好。)
  • 你能发布一个具体的例子吗?我希望简单的除法能够给出最精确的答案,而乘法版本的舍入误差会稍大一些,但是查看特定情况可以对其进行检查。

标签: c# .net math floating-point floating-point-precision


【解决方案1】:

不,这只是为了让它更快,因为乘法通常比除法更快。

Should I use multiplication or division?

1 次除法和 2 次乘法与 2 次除法可能并不总是更快,但这几乎肯定是原因。

如果向量是 3 维或更多维,我会更加相信这是值得的,但始终会针对这些微优化进行配置。

额外操作的舍入误差导致不同的结果。

【讨论】:

  • 根据 Agner Fog 的指令表,至少对于 Haswell 而言,两个完美调度的 div 需要 14 个时钟,而一个 div 和两个 mul 需要 8 个时钟。
  • 我对在上面加上确切的数字持怀疑态度。不同的处理器有不同的值。那么你指的是哪个表?加上哪些具体操作?
  • @weston:显然是 Haswell 的表 (en.wikipedia.org/wiki/Haswell_%28microarchitecture%29)。
  • 参见Agner Fog's site 的说明表手册。我正在研究 Haswell 架构的 DIVSSMULSS
  • SS = 标量单精度,即float。相反,例如PD = 压缩(向量)双精度。
【解决方案2】:

请记住,浮点的形式为 (significand * base^exponent),其中 base 最常见的是 2,significand 在底数中的位数有限,并且在区间 [1,2) 或 [0 ,1) 用于次正规。

根据 IEEE 754 标准,每个浮点运算(至少 + - * / fmod 余数 sqrt)的工作方式就像由该算法产生:

  1. 执行精确运算 (significand1 * 2^exp1) op (significand2 * 2^exp2)
  2. 根据当前有效的舍入方向将此精确结果舍入到最接近的可表示浮点数。

我简化了一点,因为还有异常值的处理、FPU异常的可编程生成等等……

因此,操作越多,舍入近似值就越灵活。

由于 * 比 / 快(尝试自己模拟那些),所以第一个分解逆运算是为了提高执行速度,但肯定不是为了提高精度。

【讨论】:

    【解决方案3】:

    恕我直言,精度应该更差而不是更好,因为您有两个操作,因此浮点近似有两个机会发挥作用......

    如果因子计算更复杂,它可能是一种节省计算两次的方法,但这里甚至不是这种情况。

    【讨论】:

    • “如果因子计算更复杂”,那就是除法。
    猜你喜欢
    • 2011-09-22
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 2022-11-02
    • 2011-12-04
    • 1970-01-01
    • 2016-06-01
    相关资源
    最近更新 更多