Teodor Mavrodiev
Teodor Mavrodiev

Reputation: 195

How do Javascript Math.max and Math.min actually work?

I am really curious how these functions actually work? I know there are a lot of questions about how to use these, I already know how to use them, but I couldn't find anywhere how to actually go about implementing this functionality on an array, for example, if there were no such functions? How would you code such a function if there were no helpers?

Upvotes: 15

Views: 15884

Answers (7)

Charlie
Charlie

Reputation: 23818

Here is the Math.max code in Chrome V8 engine.

function MathMax(arg1, arg2) {  // length == 2
  var length = %_ArgumentsLength();
  if (length == 2) {
    arg1 = TO_NUMBER(arg1);
    arg2 = TO_NUMBER(arg2);
    if (arg2 > arg1) return arg2;
    if (arg1 > arg2) return arg1;
    if (arg1 == arg2) {
      // Make sure -0 is considered less than +0.
      return (arg1 === 0 && %_IsMinusZero(arg1)) ? arg2 : arg1;
    }
    // All comparisons failed, one of the arguments must be NaN.
    return NaN;
  }
  var r = -INFINITY;
  for (var i = 0; i < length; i++) {
    var n = %_Arguments(i);
    n = TO_NUMBER(n);
    // Make sure +0 is considered greater than -0.
    if (NUMBER_IS_NAN(n) || n > r || (r === 0 && n === 0 && %_IsMinusZero(r))) {
      r = n;
    }
  }
  return r;
}

Here is the repository.

Upvotes: 15

Rick Hitchcock
Rick Hitchcock

Reputation: 35670

Below is how to implement the functions if Math.min() and Math.max() did not exist.

Functions have an arguments object, which you can iterate through to get its values.

It's important to note that Math.min() with no arguments returns Infinity, and Math.max() with no arguments returns -Infinity.

function min() {
  var result= Infinity;
  for(var i in arguments) {
    if(arguments[i] < result) {
      result = arguments[i];
    }
  }
  return result;
}

function max() {
  var result= -Infinity;
  for(var i in arguments) {
    if(arguments[i] > result) {
      result = arguments[i];
    }
  }
  return result;
}

//Tests
console.log(min(5,3,-2,4,14));       //-2
console.log(Math.min(5,3,-2,4,14));  //-2

console.log(max(5,3,-2,4,14));       //14
console.log(Math.max(5,3,-2,4,14));  //14

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

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

Upvotes: 7

Shashank
Shashank

Reputation: 13869

Well, here's min without Math.min (code is in ES6).

function min() {
  return Array.from(arguments).reduce(
    (minSoFar, next) => minSoFar < next ? minSoFar : next
  , Infinity)
}

The same logic could be implemented with a simple loop. You would just need to keep track of one of variable through your iteration, which is the lowest value you've seen so far. The initial value of minSoFar would be Infinity. The reason is that any Number except Infinity is less than Infinity, but in the case of no arguments sent, we want to return Infinity itself, because that's what Math.min() with no arguments evaluates to.

function min() {
  let minSoFar = Infinity
  for(let i = 0, l = arguments.length; i < l; i++) {
    const next = arguments[i]
    minSoFar = minSoFar < next ? minSoFar : next
  }
  return minSoFar
}

Max can be implemented with pretty much the same logic, only you're keeping track of the highest value you've seen so far, and the initial value is -Infinity.

Upvotes: 2

csga5000
csga5000

Reputation: 4141

Basic functionality:

Math.max() and Math.min() are used on numbers (or what they can coerce into numbers) you cannot directly pass an array as a parameter.

Ex:

Math.max(1,52,28)

You can have an number of comma delimited numbers.

Arrays:

This example shows how one could apply them to arrays:

JavaScript: min & max Array values?

Basically the following works:

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

Why that works?

This works because apply is a function that all functions have which applies a function with the arguments of an array.

Math.max.apply(null, [1,5,2,3]) is the same as Math.max(1,5,2,3)

Upvotes: 3

Jack
Jack

Reputation: 9388

Let's take a look at the specifications (which could/should help you in implementation!)

In ECMAScript 1st Edition (ECMA-262) (the initial definitions for both Math.max/min), we see the following:

15.8.2.11 max(x, y)
Returns the larger of the two arguments.
    • If either argument is NaN, the result is NaN.
    • If x>y, the result is x.
    • If y>x, the result is y.
    • If x is +0 and y is +0, the result is +0.
    • If x is +0 and y is −0, the result is +0.
    • If x is −0 and y is +0, the result is +0.
    • If x is −0 and y is −0, the result is −0.

15.8.2.12 min(x, y)
    Returns the smaller of the two arguments.
    • If either argument is NaN, the result is NaN.
    • If x<y, the result is x.
    • If y<x, the result is y.
    • If x is +0 and y is +0, the result is +0.
    • If x is +0 and y is −0, the result is −0.
    • If x is −0 and y is +0, the result is −0.
    • If x is −0 and y is −0, the result is −0.

Later versions of the specification give us:

ECMAScript 5.1

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.

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.

The reference to 11.8.5 can be found here: The Abstract Relational Comparison Algorithm

ECMAScript 2015

20.2.2.24 Math.max ( value1, value2 , …values )

    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 using the Abstract Relational Comparison algorithm (7.2.11) except that +0 is considered to be larger than −0.

    The length property of the max method is 2.

20.2.2.25 Math.min ( value1, value2 , …values )

    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 using the Abstract Relational Comparison algorithm (7.2.11) except that +0 is considered to be larger than −0.

The length property of the min method is 2.

And again, 7.2.11 can be found here: Abstract Relational Comparison

Upvotes: 5

Nadir Muzaffar
Nadir Muzaffar

Reputation: 4842

This is easy to implement with Array.prototype.reduce:

function min() {
   var args = Array.prototype.slice.call(arguments);

   var minValue = args.reduce(function(currentMin, nextNum) {
      if (nextNum < currentMin) {
         // nextNum is less than currentMin, so we return num
         // which will replace currentMin with nextNum
         return nextNum;
      }
      else {
         return currentMin;
      }
   }, Infinity);

   return minValue;
}

Upvotes: 0

Related Questions