爲何 Math.min() 比 Math.max() 大?(續)

昨天心血來潮寫了一篇文章:爲何Math.min() 比 Math.max() 大?javascript

爲何不少人會有這種疑惑,是由於犯了想固然的錯誤——望文生義。Math.min() 做爲一個函數,返回的並非最小值;同理 Math.max() 返回的也不是最大值。他們返回的是參數的最大值和最小值,而咱們卻沒有傳遞任何參數。前端

javascript 中數值的最大值和最小值常量分別是 Number.MAX_VALUENumber.MIN_VALUE,在我電腦 V8 的運行結果是 1.7976931348623157e+3085e-324java

這裏也有一個坑,那就是 MIN_VALUE 並非最小的數,而是絕對值最小的數,它是一個正數。而 Math.min() 的返回值比 Number.MAX_VALUE 還要大。算法

Math.min() 返回了 Infinity,這個值對應了 Number.POSITIVE_INFINITY 常量。Math.max() 返回了 -Infinity,這個值對應了 Number.NEGATIVE_INFINITY 常量。segmentfault

就像數學裏面那樣,正無窮和負無窮並非確切的數,只是集合裏面的概念。咱們可使用 0 減去正無窮來獲得負無窮:0 - Infinity = -Infinity,或者經過 0 減去負無窮來獲得正無窮:0 - (-Infinity) = Infinity。可是咱們把正無窮和負無窮相加卻得不到 0,事實上咱們獲得的是 NaN。數組

當咱們真正明白了 Math.min 和 Math.max 只是返回了全部參數的最大值,就很容易理解這個看似匪夷所思的結果了。函數

原本想查看 V8 的源碼,可是搜索了一圈,也只找到了幾個測試用例(文件: test/mjsunit/math-min-max.js):測試

assertEquals(Infinity, Math.min()); 
assertEquals(1, Math.min(1)); 
assertEquals(1, Math.min(1, 2)); 
assertEquals(1, Math.min(2, 1)); 
assertEquals(1, Math.min(1, 2, 3)); 
assertEquals(1, Math.min(3, 2, 1)); 
assertEquals(1, Math.min(2, 3, 1));

今後測試用例中能夠看出,Math.min() 確實返回了 Infinity。繼續閱讀此測試用例還會發現更有意思的事:code

assertEquals(-Infinity, Infinity / Math.min(-0, +0)); 
assertEquals(-Infinity, Infinity / Math.min(+0, -0)); 
assertEquals(-Infinity, Infinity / Math.min(+0, -0, 1));

對比下面的結果:ip

assertEquals(Infinity, Infinity / Math.max(-0, +0)); 
assertEquals(Infinity, Infinity / Math.max(+0, -0)); 
assertEquals(Infinity, Infinity / Math.max(+0, -0, -1));

也就是說在 Math.minMath.max 進行數值比較(javascript不分整型和浮點型)時,負零是小於正零的。

-0、+0、-Infinity、+Infinity、NaN 這幾個概念就能夠講上一天一晚上了,篇幅有限就不展開講了,之後有時間再填坑。

言歸正傳,如今咱們換個思路,試着從算法的角度去考慮最大值和最小值的問題。

咱們如何求 N 個參數的最大值呢?爲了描述簡單咱們使用數組(感謝 @f2er前端百科)

var max = ___;
arr.forEach(function(n) { 
    if(n > max) { 
        max = n; 
    }
});

若是是填空題,你會在空格處填什麼呢?如此想來,這個返回值就很合理了。


原本覺得是無參調用時返回了運算的幺元,後來細琢磨,好像沒有什麼關係,2333

對於運算集合 S 上的二元運算,若是知足 ax = xa = x,則 a 是運算的幺元。加法運算的幺元是 0,由於 0+x = x+0 = x。乘法運算的幺元是 1,由於 1x = x1 = x。可是咱們定義函數 add() 或者 mult() 函數,若是不傳遞參數時,返回幺元的話也是不合理的。

完。

相關文章
相關標籤/搜索