如果 y=1/x,其中 x,y 可以用浮点数表示而不四舍五入,并且 MIN_VALUE<=x,y,z,z*y<=MAX_VALUE,那么 z*y==z/x 总是真的吗?

If y=1/x which x,y can be represented by float numbers without rounding, and MIN_VALUE<=x,y,z,z*y<=MAX_VALUE, is z*y==z/x always true?

提问人:displaydisplayname 提问时间:3/21/2023 最后编辑:displaydisplayname 更新时间:3/21/2023 访问量:78

问:

我正在查看一些代码,发现有些部分使用 num/2,而另一些部分使用 num * 0.5。这启发了我一个问题:在 MIN_VALUE 和 MAX_VALUE 的范围内,num/2 和 num*0.5 可以互换吗?

我不仅对 num 除以 2 的情况感兴趣,请考虑:

  0.5 = 1/2
  4 = 1/0.25
  0.125 = 1/8

其中 y=1/x 和 x 任意 y 都可以用浮点数完美地表示。我的问题是,对于其他情况,x , y 可以用浮点数完美表示而无需四舍五入,并且 Float.MIN_VALUE<=x,y,z,z*y<=Float.MAX_VALUE,z * y == z/x 总是真的吗?

我测试了一些案例,这是真的:

document.write(123.456*4 == 123.456/0.25);
document.write("<br/>");
document.write(24.68/16 == 24.68*0.0625);
document.write("<br/>");
document.write(98.765/2 == 98.765*0.5);

我还尝试通过for循环验证一些情况:

for(let i=0;i<10000;i++){
  const r=Math.random()*10000;
  if(r*0.5!=r/2){
    document.write(r+"<br/>");
    break;
  }
}

for(let i=0;i<10000;i++){
  const r=Math.random()*10000;
  if(r*4!=r/0.25){
    document.write(r+"<br/>");
    break;
  }
}

for(let i=0;i<10000;i++){
  const r=Math.random()*10000;
  if(r*0.125!=r/8){
    document.write(r+"<br/>");
    break;
  }
}

测试了几次,没有打印出反例。但我不知道是否适用于所有其他情况。

注意:y 不包括 0.1 和 0.2 等数字,因为 0.1 和 0.2 不能完全用浮点数表示,而 0.5 和 0.25 可以。此外,y 不像 1.25,因为 x=1/1.25=0.8,而 0.8 也不能用浮点数完美表示。

JavaScript 浮点 精度

评论


答:

-1赞 gog 3/21/2023 #1

浮点数学是坏的,因此通常:(x * 1/y) != (x / y)

> 0.2 / 10
< 0.02
> 0.2 * (1/10)
< 0.020000000000000004

评论

0赞 Eric Postpischil 3/21/2023
该问题特别询问没有舍入误差的问题。换句话说,它只询问以浮点格式表示的倒数。y=1/x
3赞 Eric Postpischil 3/21/2023 #2

JavaScript 是 ECMAScript 的实现,ECMAScript 指定使用 IEEE 754 浮点标准。IEEE 754 定义了产生结果的一般运算,就好像实数算术结果是以无限精度计算的,然后根据适用的舍入规则四舍五入一样。因此,如果数学表达式 • 和 / 相等,它们必须是 if = 1/ 且没有舍入误差,则浮点计算并产生相同的结果。zyzxyxz*yz/x

具体来说,IEEE 754-2019 4.3 说:

...除非另有说明,否则每个操作都应执行,就好像它首先产生一个精确到无限精度和无限范围的中间结果,然后根据本条款中的属性之一对该结果进行舍入......

ECMAScript 2020 语言规范没有对 IEEE 754 的符合性做出一般性声明,而是单独指定操作符合性。例如,6.1.6.1.4 讨论乘法并说:

...浮点乘法的结果受 IEEE 754-2019 二进制双精度算术规则的约束:...