我知道 (-0 === 0) 結果是真的。我很想知道為什么 -0 < 0 會發生?
當我在 stackoverflow 執行背景關系中運行此代碼時,它回傳0.
const arr = [ 0, 0, -0];
console.log(Math.min(...arr));
但是當我在瀏覽器控制臺中運行相同的代碼時,它回傳-0. 這是為什么?我試圖在谷歌上搜索它,但沒有找到任何有用的東西。這個問題可能不會為某個實際示例增加價值,我想了解 JS 是如何計算它的。
const arr = [ 0, 0, -0];
console.log(Math.min(...arr)); // -0
uj5u.com熱心網友回復:
-0不低于0或者 0,兩者-0 < 0和-0 < 0回報False,你混的行為Math.min具有的比較-0與0/ 0。
的規范Math.min在這一點上很明確:
灣 如果數字是-0??,最低是 0??,則設定最低為-0??。
如果沒有這個例外,Math.minand的行為Math.max將取決于引數的順序,這可以被認為是一種奇怪的行為——你可能希望Math.min(x, y)總是相等Math.min(y, x)——所以這可能是一個可能的理由。
注意:此例外已存在于1997 年的規范中Math.min(x, y),因此不會在稍后添加。
uj5u.com熱心網友回復:
這是 的專長Math.min,具體如下:
21.3.2.25 Math.min ( ...args )
[...]
- 對于強制的每個元素數,做
一個。如果 number 是 NaN,則回傳 NaN。
灣 如果數字是-0??,最低是 0??,則設定最低為-0??。
C。如果數字 < 最低,則將最低設定為數字。
- 回報最低。
請注意,在大多數情況下, 0 和 -0 被同等對待,在 ToString 轉換中也是如此,因此(-0).toString()計算結果為"0"。您可以在瀏覽器控制臺中觀察到差異是瀏覽器的一個實作細節。
uj5u.com熱心網友回復:
這個答案的重點是解釋為什么Math.min完全可交換的語言設計選擇是有意義的。
我很想知道為什么 -0 < 0 會發生?
它不是真的; <是與“最小值”分開的操作,并且Math.min不完全基于 IEEE<比較,例如b<a ? b : a.
那將是非交換的wrt。NaN 以及有符號零。(<如果任一運算元為 NaN,則為 false,因此會產生a)。
就最小驚訝原則而言,如果Math.min(-1,NaN)是NaN但是Math.min(NaN, -1)是,它至少會同樣令人驚訝(如果不是更多的話)-1。
JS 語言設計者想要Math.minNaN 傳播,因此<無論如何都無法基于它。 他們選擇使其完全可交換,包括帶符號的零,這似乎是一個明智的決定。
OTOH,大多數代碼并不關心帶符號的零,因此這種語言設計選擇對每個人來說都需要一些性能來滿足某些人想要明確定義的帶符號零語意的罕見情況。
如果您想要一個忽略陣列中 NaN 的簡單操作,請使用current_min = x < current_min ? x : current_min. 這會忽略所有NaN,也忽略-0了current_min <= 0.0(IEEE比較)。或者如果current_min從 NaN 開始,它將保持 NaN。許多這些東西對于Math.min函式來說是不受歡迎的,所以它不能那樣作業。
如果比較其他語言,C 標準fmin函式是可交換的。NaN(如果有,則回傳非 NaN,與 JS 相對),但不需要是可交換的。簽名為零。一些 C 實作選擇像 JS 一樣作業 -0.0 for fmin/ fmax。
但是,C std::min 是一個方面純粹定義<操作,所以它做的作業的方式。(它旨在通用,包括非數字型別,如字串;不像std::fmin它沒有任何特定于 FP 的規則。)請參閱在 x86 上提供無分支 FP 最小值和最大值的指令是什么?回復:x86 的minps指令和 C std::min都是非可交換的。NaN 和符號零。
IEEE 754<沒有給出不同 FP 數字的總順序。Math.min確實,除了NaN的(例如,如果你建立了一個排序網路,它和Math.max它的順序不同意用。) Math.max:他們都回傳NaN的,如果有一個,所以采用最小/最大比較排序網路會產生所有的NaN,如果有任何的輸入陣列。
Math.min如果沒有諸如==查看回傳的 arg 之類的東西,單獨進行排序是不夠的,但是對于有符號零和 NaN 來說,這會分解。
uj5u.com熱心網友回復:
從鉻源
// ECMA 262 - 15.8.2.12
function MathMin(arg1, arg2) { // length == 2
var length = %_ArgumentsLength();
if (length == 2) {
arg1 = TO_NUMBER(arg1);
arg2 = TO_NUMBER(arg2);
if (arg2 > arg1) return arg1;
if (arg1 > arg2) return arg2;
if (arg1 == arg2) {
// Make sure -0 is considered less than 0.
return (arg1 === 0 && %_IsMinusZero(arg1)) ? arg1 : arg2;
}
// All comparisons failed, one of the arguments must be NaN.
return NaN;
}
var r = INFINITY;
for (var i = 0; i < length; i ) {
var n = %_Arguments(i);
n = TO_NUMBER(n);
// Make sure -0 is considered less than 0.
if (NUMBER_IS_NAN(n) || n < r || (r === 0 && n === 0 && %_IsMinusZero(n))) {
r = n;
}
}
return r;
}
我認為這條線return (arg1 === 0 && %_IsMinusZero(arg1)) ? arg1 : arg2;就是這個問題的答案。我假設,SO 可能使用不同的引擎來執行腳本。
uj5u.com熱心網友回復:
該規范奇怪地相互矛盾。在<比較規則明確表示,-0不小于 0。然而,規范卻Math.min()相反:如果當前(在迭代引數時)值是-0,并且到目前為止 0的最小值是,那么最小值應該設定為-0。
我希望有人為此激活 TJ Crowder 信號。
編輯- 在一些評論中建議該行為的一個可能原因是可以檢測到一個-0值,即使對于正常運算式中的幾乎所有目的,該值-0都被視為是普通的0。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/395357.html
標籤:javascript 数学 浮点 分钟 负零
