这个答案的重点是解释为什么选择Math.min完全可交换的语言设计是有意义的。
我很想知道为什么 -0 < 0 会发生?
它不是真的;<是与“最小值”分开的操作,并且Math.min不仅仅基于 IEEE<比较,例如b<a ? b : a.
那将是不可交换的。NaN 以及有符号零。(<如果任一操作数为 NaN,则为假,因此会产生a)。就最小惊讶原则而言,如果 is but
is 至少会令人惊讶(如果不是更多的话Math.min(-1,NaN))。NaNMath.min(NaN, -1)-1
JS 语言的设计者想要Math.min成为 NaN 传播,所以仅仅基于它<是不可能的。 他们选择使其完全可交换,包括有符号零,这似乎是一个明智的决定。
OTOH,大多数代码都不关心有符号零,因此这种语言设计选择会为每个人花费一些性能,以迎合某些人想要定义良好的有符号零语义的罕见情况。
如果您想要一个忽略数组中 NaN 的简单操作,请使用current_min = x < current_min ? x : current_min. 这将忽略所有 NaN,也忽略-0(current_min <= +0.0IEEE 比较)。或者如果current_min开始是 NaN,它将保持 NaN。其中许多事情对于Math.min函数来说是不可取的,所以它不能那样工作。
如果你比较其他语言,C 标准fmin函数是可交换的。NaN(如果有,则返回非 NaN,与 JS 相反),但不需要是可交换的。签名为零。一些 C 实现选择像 JS for +-0.0 for fmin/一样工作fmax。
但是C++std::min 纯粹是根据操作定义的,<所以它确实以这种方式工作。(它旨在通用地工作,包括像字符串这样的非数字类型;不像std::fmin它没有任何特定于 FP 的规则。)请参阅在 x86 上提供无分支 FP min 和 max 的指令是什么?回复:x86 的minps指令和 C++std::min都是不可交换的。NaN 并签名为零。
IEEE 754<不会为您提供不同 FP 编号的总顺序。Math.min除了 NaN(例如,如果你用它和Math.max.Math.max输入数组。
Math.min如果没有类似查看它返回哪个 arg 的东西,单独进行排序是不够的==,但是对于有符号零和 NaN 来说,这会分解。