Round 函数保证生成最佳浮点近似?

Round function guaranteed to generate the best floating point approximation?

提问人:David Vonka 提问时间:9/25/2023 最后编辑:David Vonka 更新时间:9/26/2023 访问量:49

问:

当我运行时,我是否保证得到相同的浮点近似值(3.1200000000000000010658141036401502788066864013671875 ) 当我使用文字时我得到的?round(3.12143345454353,2)3.12

换句话说,round(3.12143345454353,2)===3.12 会是真的吗?一般来说是这样吗,所以如果 x 舍入到 y,浮点算术是否保证 round(x,k)===y?

JavaScript Python 浮点

评论

2赞 Marc Le Bihan 9/25/2023
我建议你添加你正在使用的语言的标签。Javascript?
1赞 Tim Roberts 9/25/2023
我不认为有任何保证,没有。与浮点数一起使用几乎从来都不安全。==
1赞 chtz 9/25/2023
“如果 x 舍入到 y,浮点运算是否保证 round(x,k)===y” 这不是重言式吗?(不过,您需要添加一个语言标签,并可能在什么设备上/编译器/解释器/...你正在运行)
2赞 Eric Postpischil 9/25/2023
C 甚至不能保证这一点并具有相同的值(除非在 C 2023 中对此进行了更改)。C 2018 注 77 至 6.4.4.2 5 说“、 和都是不同的源形式,因此不需要转换为相同的内部格式和值。这种宽容性使我们感到复杂,因为在计算中,解析了 和 之类的东西。如果按照 IEEE-754 的规定进行正确的舍入分析,则结果将相同。1.231.2301.231.230123e-2123e-021.23L123456789…123456789e-1001.23456789…123456789
1赞 chux - Reinstate Monica 9/25/2023
@David Vonka,“换句话说,round(3.12143345454353,2)===3.12 是真的>吗?发布函数的定义以了解详细信息。round(x,i)

答:

0赞 chux - Reinstate Monica 9/25/2023 #1

是的,也不是。
这取决于舍入模式和实施质量。
round()

代码到值的编译时转换取决于舍入的语言编译器选项。转换为最接近的 binary64 值(如 (13))非常常见。3.123.120000000000000106...0

根据上下文和语言,源代码 like 甚至可以转换为更高精度的数学,因此具有类似于 3.11999999999999999999959 的值......(16 ),3.129

如果假定的函数(四舍五入到最接近的 10-d)存在,则即使调用 .David_Vonka_round(x, d)David_Vonka_round([digits].[digit][digit]0, 2)

在 C 中考虑以下几点

// Weak rounding code
double David_Vonka_round(double x, int d) {
  pow10 = pow(10, d);
  // Note that `x * pow10` incurs a rounded product.
  // Note that `product + 0.5` incurs a rounded sum.
  long long y = (long long) (x * pow10 + 0.5);
  // A 3rd operation
  return y/pow10;
}
  

前 2 个数学运算,除非以更高的精度完成,否则会产生可能与预期数学运算不同的结果。这与 几乎没有区别。(它与以下值有重要区别yDavid_Vonka_round([digits].[digit][digit]0, 2)David_Vonka_round([digits].[digit][digit]5, 2))

这 3 个数学运算也受当前舍入模式(最接近、向上、向下、趋近于零等)的约束,该模式可能与编译期间使用的舍入模式不同。然后,第三个运算符可以在运行时形成与编译代码不同的值。/


一般来说,OP 可以预期相同,但边缘情况、变体舍入模式和弱代码都会导致差异。

评论

0赞 David Vonka 9/26/2023
那么,如果上面的代码很弱,那么好的实现有什么作用呢?
0赞 chux - Reinstate Monica 9/26/2023
@DavidVonka 更好的代码不会溢出。通过测试全部为整数的大值或使用更广泛的数学。通过精确的数学运算(更宽的类型或额外的代码)按 10 的幂进行缩放。当大于 5 时,要想做好这项任务,正确处理边缘情况可能会非常困难。d