当我在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
但是,当我使用没有参数的函数时,它会返回错误的答案:
console.log( Math.min() ); // Infinity
console.log( Math.max() ); // -Infinity
这个返回false:
console.log( Math.min() < Math.max() );
为什么这样做?
答案 0 :(得分:44)
当然可以,因为Infinity
的起始编号应为Math.min
。如果没有较小的数字,那么低于正无穷大的所有数字应该是列表中最小的数字。
对于Math.max
它是一样的;如果没有更大的数字,所有大于负无穷大的数字应该是最大的。
所以对于你的第一个例子:
Math.min(5)
其中5
小于正无穷大(Infinity
),它将返回5
。
使用数组参数调用Math.min()
和Math.max
可能无法在每个平台上运行。您应该执行以下操作:
Math.min.apply(null, [ 1, 2, 3, 4 , 5 ]);
第一个参数是范围参数。因为Math.min()
和Math.max()
是“静态”函数,所以我们应该将scope参数设置为null。
答案 1 :(得分:31)
在传递空集时,正确决定聚合函数应该做什么是很棘手的,但很重要。
有时它“直观明显”:没有元素的总和是什么?零,我相信每个人都会说。
有时它不那么:没有元素的产品是什么?那些接受过数学训练的人很快会说“一”,但这一点并不明显。
然后你到达MIN和MAX并且哇!我们是如何获得这些无限的?
决定聚合函数在这里应该做什么的一种方法是考虑我们希望保持一致的行为,即使是空集。例如,假设我们有这些非空集:
A = { 1, 2, 3 }
B = { 4, 5 }
现在,这里确实如此,对于任何非空集,确实如此
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)
数学家们说,如果这些属性仍然是真的,即使其中一个或两个都是空的,这不是很好吗?肯定会的。
这是这个行为决定了我们分配给SOME_AGGREGATE_FUNCTION(empty-set)
的值:
为了
SUM(A union B) = SUM(SUM(A), SUM(B))
当A
为空并且B
不为时,保持为真,我们必须SUM(empty-set) = 0
为了
PRODUCT(A union B) = PRODUCT(PRODUCT(A), PRODUCT(B))
当A
为空并且B
不为时,保持为真,我们必须PRODUCT(empty-set) = 1
最后:
为了
MIN(A union B) = MIN(MIN(A), MIN(B))
当A
为空并且B
不为时,保持为真,我们需要MIN(empty-set)
为一个保证大于B中任何可能值的值,以便它不会“干扰”MIN(B)
的结果。我们得到了答案:MIN(empty-set) = positive infinity
答案 2 :(得分:19)
为什么会这样做?
因为那应该发生the standard says;
15.8.2.11 max([value1 [,value2 [,...]]])
给定零个或多个参数,在每个参数上调用ToNumber并返回最大的结果值。
- 如果没有给出参数,则结果为-Infinity
- 如果任何值为NaN,则结果为NaN。
- 确定最大值的值的比较按照11.8.5进行,但认为+0大于0。
15.8.2.12 min([value1 [,value2 [,...]]])
给定零个或多个参数,在每个参数上调用ToNumber并返回最小的结果值。
- 如果没有给出参数,则结果为无限。
- 如果任何值为NaN,则结果为NaN。
- 除了考虑+0之外,用于确定最小值的值的比较如11.8.5中所述 大于0
P.S; Math.max()
或Math.min()
接受数组是非标准的。请改用Math.max(a,b,c,d,e,...)
等。
至少在Chrome中;
Math.max([1,2,3,4]); // NaN
答案 3 :(得分:14)
这与为什么空列表的总和通常定义为0并且它们的乘积为1的原因相同:它是操作的标识元素。也就是说,只要在计算max时将-Infinity包含为元素,它就不会影响结果;分别为Infinity和min。
这是明智的,因为它允许聚合操作具有理想的“关联”属性。例如,列表的总和与计算任何子列表的总和(可能包括空)和对它们求和相同。同样适用于产品,分钟,最大值等。
答案 4 :(得分: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];
}
}
(事实上,可能只是标准使Math.min
的实现变得更容易,因为它可能会先将结果初始化为+ Infinity,然后再对其进行处理参数存在,使用类似于上面的算法。)
当然,这个例子有点人为,因为我们可以写:
var x = Math.min(a[0], a[1], a[2], a[3], a[4]);
但是,如果我们不知道数组中元素的数量,则循环很有用,因为您使用的Math.min
变体接受数组是非标准的。
即使这样,你也可以这样做:
var x = Math.min.apply(null, a);
// ^ reflective function-call
// ^ no object instance; function is "static"
// ^ array of arguments
答案 5 :(得分:7)
可能是因为在开始与空数组进行比较之前,实现将内部比较变量初始化为最高(对于Math.min)或最低(对于Math.max),然后返回此内部比较变量的值。当然没有改变。
答案 6 :(得分:3)
我不确定。但是,只是猜猜。
记住我们如何找到分钟。声明一个具有极高值(无穷大)的变量,然后遍历这些值,每当您发现一个小于变量中存储的值时,就将其存储为新的最小值。
所以,既然你没有给它任何值来找到min,它会给你初始值,即Infinity。
最大相同
答案 7 :(得分:0)
如果没有参数,Math.min()
等于无穷大,Math.max()
为-infinity
。
这可能是为了确保任何值都小于目前为止的最小值,并且大于目前为止的最大值。
答案 8 :(得分:0)
这个想法是,在数学上没有任何参数,你实际上有一个未定义的最小值。
至于实现方式,通常使用非常大的值(无穷大)初始化最小值,然后在找到较小的值时更新。如果未找到任何值,则您将Infinity
作为最小值。
案例与查找最大值相反,这就是-Infinity
的原因。
答案 9 :(得分:0)
理论上,这些功能的结果是不能给出的。 Ecma specification规定了没有参数的Min和Max函数的结果(参见第163页)。
显然,你可以对结果应该有各种各样的争论,但无论如何都没有严格正确的答案。我猜Ecma会选择这个,因为它最容易实现。通常,max函数大致类似于
result = -infinity;
foreach(arg in arguments)
if(arg > result)
result = arg;
如您所见,在没有参数的情况下调用函数时返回-infinity不需要任何更改。