Javascript中浮点数的精度可以成为非确定性的来源吗?

Can precision of floating point numbers in Javascript be a source of non determinism?

本文关键字:确定性 非确定 浮点数 精度 Javascript      更新时间:2023-09-26

相同的数学运算在不同的架构或浏览器中可以返回不同的结果吗?

其他答案不正确。 根据 ECMAScript 5.1 规范(第 15.8.2 节)

注意 函数 acos, asin, atan, atan2, cos, exp, log、pow、sin、sqrt 和 tan 在这里没有精确指定,除了 要求某些参数值的特定结果表示 感兴趣的边界案例。

虽然算法的选择是 留给实现,建议(但不指定 该标准)的实现使用近似算法 对于包含在 fdlibm 中的 IEEE 754 算法,可自由分发 Sun Microsystems 的数学库


但是,即使指定了实现,所有浮点运算的确切结果仍将取决于浏览器/体系结构。 这包括乘法和除法等简单操作!!

原因是IEEE-754允许系统以比结果更高的精度进行64位浮点计算,导致舍入结果与使用与结果相同精度的系统不同。 这正是x86(英特尔)架构所做的,这就是为什么在C(和javascript)中,我们有时可以拥有cos(x) != cos(y),即使x == y ,即使在同一台机器上!

对于联网的点对点游戏来说,这是一个大问题,因为这意味着,如果不能禁用更高精度的计算(就像 C# 的情况一样),这些游戏几乎根本无法使用浮点计算。 但是,对于Javascript游戏来说,这通常不是问题,因为它们通常是客户端-服务器。

如果我们假设每个浏览器供应商都遵循IEEE标准+ ECMA规范,并且在实现时没有人为错误,那么就不会有任何区别。

尽管 ECMAScript 语言规范 5.1 版指出数字是对应于 IEEE 754 浮点数的原始值,这意味着计算应该是一致的:

http://www.ecma-international.org/publications/files/ecma-st/ECMA-262.pdf

4.3.19 数值

对应于双精度 64 位二进制格式 IEEE 754 值的基元值

注意 数字值是数字类型的成员,是数字的直接表示形式。

正如BlueRaja指出的那样,在第15.8.2节中有一个警告:

函数 acos, asin, atan, atan2, cos, exp, log, Pow,Sin,sqrt和tan在这里没有精确指定...

这意味着,这些至少是一些情况,其中数字运算的结果取决于实现,因此可能不一致。

我的两分钱 - @goldilocks笔记和其他暗示你不应该在浮点数上使用 == 或 !=。 那么"确定性"是什么意思呢? 行为在不同的机器上总是相同的? 显然,这取决于你所说的"相同的行为"是什么意思。

好吧,在一个愚蠢的"相同"字面级别上,当然不是,物理位在例如 32 位和 64 位机器上会有所不同。 所以解释出来了。

好的,那么任何程序都会在两台不同的机器上运行相同的输出吗? 在一般语言中,不可以,因为C程序可以使用未定义的内存执行某些操作,例如从未初始化的位中读取。

好的,那么任何有效的程序都会在不同的机器上做同样的事情吗? 好吧,我会说在浮点数上使用 == 和 != 的程序与读取未初始化内存的程序一样无效。 我个人不知道 Javascript 标准是否敲定了 == 和 != 在浮点数上的行为,以至于它即使不是古怪的,也是明确定义的,所以如果这是你的精确问题,你将不得不看到其他答案。 你能编写与标准相关的未定义输出的 JavaScript 代码吗? 永远不要阅读标准(其他答案在某种程度上涵盖了这一点),但就我的兴趣而言,这是没有意义的,因为会产生你所谓的不确定行为的程序一开始是无效的。