为什么选择Math.min()> Math.max()?

use*_*294 34 javascript math if-statement max min

当我在javascript数学最小和最大函数的参数中输入数组时,它返回正确的值:

console.log( Math.min( 5 ) ); // 5
console.log( Math.max( 2 ) ); // 2

var array = [3, 6, 1, 5, 0, -2, 3];
var minArray = Math.min( array ); // -2
var maxArray = Math.max( array ); // 6
Run Code Online (Sandbox Code Playgroud)

但是,当我使用没有参数的函数时,它返回一个错误的答案:

console.log( Math.min() ); // Infinity
console.log( Math.max() ); // -Infinity
Run Code Online (Sandbox Code Playgroud)

这个返回false:

console.log( Math.min() < Math.max() );
Run Code Online (Sandbox Code Playgroud)


为什么这样做?

KAR*_*ván 46

当然会,因为起始编号应InfinityMath.min.如果没有较小的数字,那么低于正无穷大的所有数字应该是列表中最小的数字.

因为Math.max它是一样的; 如果没有更大的数字,所有大于负无穷大的数字应该是最大的.

所以对于你的第一个例子:

Math.min(5)哪里5小于正无穷大(Infinity)它将返回5.

更新

调用Math.min()Math.max使用数组参数可能无法在每个平台上运行.您应该执行以下操作:

Math.min.apply(null, [ 1, 2, 3, 4 , 5 ]);
Run Code Online (Sandbox Code Playgroud)

第一个参数是scope参数.因为Math.min()并且Math.max()是"静态"函数,我们应该将scope参数设置为null.

  • 有一个完美的感觉 (4认同)
  • 这是智能但不体贴的设计师的完美例子,他们认为理论比可用性更重要.我明白为什么你建议这个"开始数字"的概念是理智的甚至是正确的,但在我看来,这就是算法/实现泄漏到结果中.对于任何接近该语言的人来说,这一点都不会显而易见 - 在读取`Math.min()`作为一行代码时,我希望它返回的最后一件事是Infinity(最大可能的数字).我很欣赏JS,但我会把它直接放在"令人遗憾的决定"类别中. (3认同)
  • 我没有投票,因为我不同意这个设计,我实际上对下面的答案提出了同样的建议,但是更详细.你得到我的downvote纯粹是因为"当然会......". (2认同)

Aak*_*shM 31

传递空集合时,正确决定聚合函数应该做什么是很棘手但很重要的.

有时它"直观明显":没有元素的总和是什么?零,我相信每个人都会说.

有时它不那么:没有元素的产品是什么?那些接受过数学训练的人很快会说"一",但这一点并不明显.

然后你到达MIN和MAX并且哇!我们是如何获得这些无限的?


决定聚合函数应该做什么的一种方法是考虑我们希望保持一致的行为,即使是空集也是如此.例如,假设我们有这些非空集:

A = { 1, 2, 3 } 
B = { 4, 5 }
Run Code Online (Sandbox Code Playgroud)

现在,这是真的,对于任何非空集,都是如此

SUM(A union B) = SUM(SUM(A), SUM(B))
15 = 6 + 9

PRODUCT(A union B) = PRODUCT(PRODUCT(A), PRODUCT(B))
120 = 6 * 20

MIN(A union B) = MIN(MIN(A), MIN(B))
1 = MIN(1, 4)
Run Code Online (Sandbox Code Playgroud)

数学家们说,即使这些属性中的一个或两个都是空的,这些属性是否仍然存在,这不是很好吗?肯定会的.

维持这种行为可以决定我们分配的值SOME_AGGREGATE_FUNCTION(empty-set):

为了

SUM(A union B) = SUM(SUM(A), SUM(B))
Run Code Online (Sandbox Code Playgroud)

如果A是空的而B不是,我们必须拥有SUM(empty-set) = 0

为了

PRODUCT(A union B) = PRODUCT(PRODUCT(A), PRODUCT(B))
Run Code Online (Sandbox Code Playgroud)

如果A是空的而B不是,我们必须拥有PRODUCT(empty-set) = 1

最后:

为了

MIN(A union B) = MIN(MIN(A), MIN(B))
Run Code Online (Sandbox Code Playgroud)

如果A是空的并且B不是,则保持为真,我们需要MIN(empty-set)保证一个值大于B中的任何可能值,以便它不会"干扰"结果MIN(B).我们得到了答案:MIN(empty-set) = positive infinity


Mat*_*att 20

为什么这样做?

因为那就是标准所说的应该发生的事情;

15.8.2.11 max([value1 [,value2 [,...]]])

给定零个或多个参数,在每个参数上调用ToNumber并返回最大的结果值.

  • 如果没有给出参数,则结果为-Infinity
  • 如果任何值是NaN,则结果为NaN.
  • 确定最大值的值的比较如11.8.5中所述,除了认为+0大于0.

15.8.2.12 min([value1 [,value2 [,...]]])

给定零个或多个参数,在每个参数上调用ToNumber并返回最小的结果值.

  • 如果没有给出参数,则结果为Infinity.
  • 如果任何值是NaN,则结果为NaN.
  • 用于确定最小值的值的比较按照11.8.5进行,除了认为+0大于0

PS; 它是非标准的Math.max()Math.min()接受数组.请Math.max(a,b,c,d,e,...)改用.

至少在Chrome中;

Math.max([1,2,3,4]); // NaN
Run Code Online (Sandbox Code Playgroud)


Juh*_*man 14

这就是为什么空列表的总和通常被定义为0并且它们的乘积为1的原因相同:它是操作的标识元素.也就是说,只要在计算max时将-Infinity包含为元素,它就不会影响结果; 分别为Infinity和min.

这是明智的,因为它允许聚合操作具有理想的"关联"属性.例如,列表的总和与计算任何子列表的总和(可能包括空)和对它们求和相同.同样适用于产品,分钟,最大值等.


Lig*_*ica 10

[ECMA-262: 15.8.2.11]: max ( [ value1 [ , value2 [ , ... ] ] ] )

给定零个或多个参数,在每个参数上调用ToNumber并返回最大的结果值.

  • 如果没有给出参数,则结果为-∞.
  • 如果有任何值NaN,结果是NaN.
  • 确定最大值的值的比较如11.8.5中所述,除了认为+0大于-0.

该方法的length属性max是2.

[ECMA-262: 15.8.2.12]: min ( [ value1 [ , value2 [ , ... ] ] ] )

给定零个或多个参数,在每个参数上调用ToNumber并返回最小的结果值.

  • 如果没有给出参数,则结果为+∞.
  • 如果有任何值NaN,结果是NaN.
  • 用于确定最小值的值的比较按照11.8.5进行,除了认为+0大于-0.

该方法的length属性min是2.

如果没有参数,Math.min则可以使用一个值来计算迭代最小值,而不是该类型的物理最小值.它通过相反的方式来实现:类型的物理最大值.(同样在另一个方向Math.max; 显然+? < -?false.)

var a = [1,2,3,4,5];
var x = Math.min();
for (var i = 0; i < a.length; i++) {
    if (a[i] < x) { // will succeed on first iteration
                    // because `x` is initialised to highest possible value
       x = a[i];
    }
}
Run Code Online (Sandbox Code Playgroud)

(事实上​​,可能只是标准使得实现Math.min变得更容易,因为它可能在使用类似于上面的算法对任何存在的参数进行处理之前将其结果初始化为+ Infinity.)

当然,这个例子有点人为,因为我们可以写:

 var x = Math.min(a[0], a[1], a[2], a[3], a[4]);
Run Code Online (Sandbox Code Playgroud)

但是,如果我们不知道数组中元素的数量,则循环很有用,因为Math.min您使用的变量接受数组是非标准的.

即使这样,你也可以这样做:

 var x = Math.min.apply(null, a);
 //               ^ reflective function-call
 //                     ^ no object instance; function is "static"
 //                           ^ array of arguments
Run Code Online (Sandbox Code Playgroud)


Ric*_*ard 7

可能是因为在开始与空数组进行比较之前,实现将内部比较变量初始化为最高(对于Math.min)或最低(对于Math.max),然后返回此内部比较变量的值,该变量当然具有没有改变.