auroranil
auroranil

Reputation: 2661

Why does Math.min() return positive infinity, while Math.max() returns negative infinity?

When I type in an array into the parameter of the javascript math minimum and maximum functions, it returns the correct value:

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

However, when I use the function with no parameters, it returns an incorrect answer:

console.log( Math.min() ); // Infinity
console.log( Math.max() ); // -Infinity

This one returns false:

console.log( Math.min() < Math.max() );

Why does it do this?

Upvotes: 42

Views: 23332

Answers (10)

Matt
Matt

Reputation: 75317

Why does it do this?

Because thats what the standard says should happen;

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

Given zero or more arguments, calls ToNumber on each of the arguments and returns the largest of the resulting values.

  • If no arguments are given, the result is -Infinity
  • If any value is NaN, the result is NaN.
  • The comparison of values to determine the largest value is done as in 11.8.5 except that +0 is considered to be larger than −0.

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

Given zero or more arguments, calls ToNumber on each of the arguments and returns the smallest of the resulting values.

  • If no arguments are given, the result is Infinity.
  • If any value is NaN, the result is NaN.
  • The comparison of values to determine the smallest value is done as in 11.8.5 except that +0 is considered to be larger than −0.

p.s; It is non standard that Math.max() or Math.min() accepts an array. Use Math.max(a,b,c,d,e,...) etc instead.

In Chrome at least;

Math.max([1,2,3,4]); // NaN

Upvotes: 19

AakashM
AakashM

Reputation: 63358

It's tricky, but important, to decide correctly what aggregate functions should do when passed the empty set.

Sometimes it's 'intuitively obvious': What is the SUM of no elements? Zero, I'm sure everyone would readily say.

Sometimes it's less so: What is the PRODUCT of no elements? Those with some mathematical training will quickly say "one", but this is not at all obvious.

Then you get to MIN and MAX and wow! How did we get those infinities?


One way to decide what an aggregate function should do here is consider what behaviours we want to remain consistent, even with empty sets. For example, suppose we have these non-empty sets:

A = { 1, 2, 3 } 
B = { 4, 5 }

Now, it's true here, and indeed for any non-empty sets, that

SUM(A ∪ B) = SUM({SUM(A), SUM(B)})
15 = 6 + 9

PRODUCT(A ∪ B) = PRODUCT({ PRODUCT(A), PRODUCT(B) })
120 = 6 * 20

MIN(A ∪ B) = MIN({ MIN(A), MIN(B) })
1 = MIN(1, 4)

Wouldn't it be nice, say the mathematicians, if these properties remain true even when one or both of the sets are empty? It surely would.

And it's maintaining this behaviour that decides what value we assign to SOME_AGGREGATE_FUNCTION(∅) :

In order for

SUM(A ∪ B) = SUM({ SUM(A), SUM(B) })

to remain true when A is empty and B is not, we must have SUM(∅) = 0

In order for

PRODUCT(A ∪ B) = PRODUCT({ PRODUCT(A), PRODUCT(B) })

to remain true when A is empty and B is not, we must have PRODUCT(∅) = 1

And finally:

In order for

MIN(A ∪ B) = MIN({ MIN(A), MIN(B) })

to remain true when A is empty and B is not, we need MIN(∅) to be a value which is guaranteed to be greater than any possible value in B, so that it doesn't 'interfere with' the result of MIN(B). And we get our answer: MIN(∅) = +∞

Upvotes: 39

KARASZI Istv&#225;n
KARASZI Istv&#225;n

Reputation: 31467

Of course it would, because the start number should be Infinity for Math.min. All number that are lower than positive infinity should be the smallest from a list, if there are no smaller.

And for Math.max it's the same; all numbers that are larger than negative infinity should be the biggest if there are no bigger.

So for your first example:

Math.min(5) where 5 is smaller than positive infinity (Infinity) it will return 5.

Update

Calling Math.min() and Math.max with an array parameter may not work on every platform. You should do the following instead:

Math.min.apply(null, [ 1, 2, 3, 4 , 5 ]);

Where the first parameter is the scope argument. Because Math.min() and Math.max() are "static" functions, we should set the scope argument to null.

Upvotes: 50

Juho &#214;stman
Juho &#214;stman

Reputation: 1584

It's the same reason why the sum of an empty list is usually defined as 0 and their product as 1: it is the identity element of the operation. That is, whenever you include -Infinity as an element when computing max, it does not affect the result; respectively for Infinity and min.

This is sensible because it allows desirable "associative" properties for the aggregate operations. For example, the sum of a list is the same as computing the sums of any sublists (maybe including empty) and summing them. Likewise for products, mins, maxes and so on.

Upvotes: 16

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385264

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

Given zero or more arguments, calls ToNumber on each of the arguments and returns the largest of the resulting values.

  • If no arguments are given, the result is −∞.
  • If any value is NaN, the result is NaN.
  • The comparison of values to determine the largest value is done as in 11.8.5 except that +0 is considered to be larger than -0.

The length property of the max method is 2.

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

Given zero or more arguments, calls ToNumber on each of the arguments and returns the smallest of the resulting values.

  • If no arguments are given, the result is +∞.
  • If any value is NaN, the result is NaN.
  • The comparison of values to determine the smallest value is done as in 11.8.5 except that +0 is considered to be larger than -0.

The length property of the min method is 2.

With no arguments, Math.min is a value you can use to calculate an iterative minimum, not a physical minimum value for the type. It does this by being the opposite: a physical maximum value for the type. (Similarly in the other direction for Math.max; and clearly +∞ < -∞ is false.)

i.e.

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];
    }
}

(In fact, it may simply be that the standard is making implementation of Math.min easier, since it probably initialises its result to +Infinity before doing its work on any argument present, using an algorithm similar to the above.)

Of course, this example is slightly contrived since we could just write:

 var x = Math.min(a[0], a[1], a[2], a[3], a[4]);

However, the loop is useful if we don't know the number of elements in the array, since the variant of Math.min you're using that accepts an array is non-standard.

Even then, you can do:

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

Upvotes: 9

AVee
AVee

Reputation: 3402

Theoretically the outcome of those functions is can't be given. The Ecma specification dictates the outcome of the Min and Max functions without arguments (See page 163).

Obviously you can have all sort of arguments about what the outcome should be, but there isn't a strictly correct answer anyway. I guess Ecma choose this because it's the easiest to implement. Normally a max function works roughly like this

result = -infinity;
foreach(arg in arguments)
    if(arg > result)
        result = arg;

As you can see, returning -infinity when the function is called without arguments requires no changes at all.

Upvotes: -1

Shamim Hafiz - MSFT
Shamim Hafiz - MSFT

Reputation: 22114

The idea is, mathematically without any parameter you actually have an undefined value for the minimum.

As for implementation wise, usually the min value is initialized with a very large value(Infinity), which is then updated as smaller values are found. If no value is found, then you have Infinity as the min value.

The case is opposite with finding the maximum value and that is why you have -Infinity .

Upvotes: -1

Divya
Divya

Reputation: 2622

I don't know for sure. But, just making a guess.

Remember how we find the min. Declare a variable with an extremely high value (Infinity) and then go through the values and whenever you find a value which is less than the one stored in your variable, you store it instead as the new min.

So, since you are not giving it any values to find the min for, it gives you the initial value i.e. Infinity.

Same for max.

Upvotes: 4

visitor
visitor

Reputation: 1801

When given no arguments, Math.min() equals infinity and Math.max() is -infinity.

This is probably to ensure that any value is smaller than the minimum found so far, and larger than the maximum so far.

Upvotes: -1

Richard
Richard

Reputation: 9928

Probably because the implementation initialises an internal comparison variable to the highest (for Math.min) or lowest (for Math.max), before starting to compare against the empty arrays, and then returns the value of this internal comparison variable which of course has not been changed.

Upvotes: 7

Related Questions