昨天心血来潮写了一篇文章:为何Math.min() 比 Math.max() 大?javascript
为何不少人会有这种疑惑,是由于犯了想固然的错误——望文生义。Math.min()
做为一个函数,返回的并非最小值;同理 Math.max()
返回的也不是最大值。他们返回的是参数的最大值和最小值,而咱们却没有传递任何参数。前端
javascript 中数值的最大值和最小值常量分别是 Number.MAX_VALUE
和 Number.MIN_VALUE
,在我电脑 V8 的运行结果是 1.7976931348623157e+308
和 5e-324
。java
这里也有一个坑,那就是 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.min
和 Math.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() 函数,若是不传递参数时,返回幺元的话也是不合理的。
完。