Math.round(intA/intB) 是否总是在每台设备上返回相同的结果?

Will Math.round(intA/intB) always return the same on every device?

提问人:Curtis 提问时间:3/29/2023 最后编辑:Curtis 更新时间:3/29/2023 访问量:48

问:

我担心像 7/2 这样的东西可能会在某些计算机上变成 3.499999999 而不是 3.5,然后四舍五入为 3 而不是 4。这可能吗?

我需要每台计算机都精确地重新运行相同的数学运算。这是我唯一一次有浮点数:Math.round(intA/intB)

JavaScript 浮点精度 math.round

评论

0赞 OldProgrammer 3/29/2023
这回答了你的问题吗?浮点数学坏了吗?
1赞 ShadowRanger 3/29/2023
我想你的意思是可能会成为这些价值观之一?7/2
2赞 Terry 3/29/2023
它在所有设备上都是相同的,因为 JS 使用 IEEE754 标准。它被称为标准是有充分理由的。
0赞 Curtis 3/29/2023
是的,我的意思是 7/2 或任何最后应该有 .5 的东西都可以改为 .49999。如果它们都使用相同的标准,我想我不必担心某些设备会为某些用户以不同的方式重播我的数据,谢谢!
1赞 ShadowRanger 3/29/2023
@OldProgrammer:对于任何对二进制浮点有疑问的人来说,这都是一件有用的事情,但它绝不是重复的。在任何情况下,它所谈论的错误甚至不会发生整数除以。2

答:

3赞 ShadowRanger 3/29/2023 #1

您的问题分为两部分:

  1. 每个可表示的整数值除以 精确到 的倍数吗?2.5
  2. 会随身携带吗?Math.round

两者的答案都应该是肯定的(尽管显然实现者可以做一些奇怪的事情)。具体说来:

  • IEE-754 二进制浮点值(JS 是以 binary64 形式实现的)使用基于 2 幂的比例因子;因此,任何可表示的整数值都可以除以而不会造成精度损失;要么是均匀除法(不需要比例因子),要么是奇数,比例因子用于内部存储,基本上是“原始值除以”。NumberNumber22**1

  • 规范要求 Math.round 向正无穷大四舍五入

    如果小数部分正好是 0.5,则参数将沿 +∞ 方向舍入到下一个整数。

在这两个保证之间,您无需担心; 将永远是精确的,并且将永远是.只有当你除以非 2 的幂(或巨大的 2 的幂)时,或者你除以不是精确整数的东西时,错误才会悄悄出现。7/23.5Math.round(7/2)4

如果你正在做一些在 IEEE-754 二进制浮点中产生不精确结果的事情,它将是不精确的,但它应该是可移植的不精确的;JS 不是 C,该规范明确要求双精度 64 位二进制格式 IEEE 754,而不是“无论处理器碰巧提供什么”,因此您不必担心提供与 IEEE-754 不兼容的浮点的深奥硬件(如果硬件不支持它,任何兼容的 JS 引擎都需要在软件中实现它)。

评论

0赞 Curtis 3/29/2023
等等,所以我可能不得不担心像 9/6 这样的事情?我实际上正在做一些 RandomInt/n,其中 n 从 2 到 9 循环。所以 6 是唯一不是 2 的幂并且可以给出 x.5 的 n
0赞 ShadowRanger 3/29/2023
@Curtis:我相信,如果它能被除 2 个因素的幂之外的所有因素平均整除,你应该没问题。所以抵消一个 ,留下 ,这是无损的。当非 2 次幂除数触发无法以 2 为基数表示的值的近似值时,就会出现问题。因此,如果您通过 (这在逻辑上只是 ),第一步将不精确,因此结果实际上可能不是(我没有检查)。但是,如果它是一个文字整数值除以 ,你就很清楚了。9 / 633 / 299 / 27 * 9 * 39996
0赞 Eric Postpischil 3/29/2023
关于“不精确的结果”:问题在于准确性(获得值的忠实度)而不是精确度(表示值的精细度)。IEEE-754 中的所有普通数字都具有相同的精度。