Javascript как найти наибольшее число

How about augmenting the built-in Array object to use Math.max/Math.min instead:

Array.prototype.max = function() {
  return Math.max.apply(null, this);
};

Array.prototype.min = function() {
  return Math.min.apply(null, this);
};

let p = [35,2,65,7,8,9,12,121,33,99];

console.log(`Max value is: ${p.max()}` +
  `nMin value is: ${p.min()}`);

Here is a JSFiddle.

Augmenting the built-ins can cause collisions with other libraries (some see), so you may be more comfortable with just apply‘ing Math.xxx() to your array directly:

var min = Math.min.apply(null, arr),
    max = Math.max.apply(null, arr);

Alternately, assuming your browser supports ECMAScript 6, you can use spread syntax which functions similarly to the apply method:

var min = Math.min( ...arr ),
    max = Math.max( ...arr );

RobG's user avatar

RobG

141k31 gold badges172 silver badges209 bronze badges

answered Nov 3, 2009 at 18:23

Roatin Marth's user avatar

Roatin MarthRoatin Marth

23.5k3 gold badges51 silver badges55 bronze badges

15

Using spread operator (ES6)

Math.max(...array)  // The same with "min" => Math.min(...array)

Gass's user avatar

Gass

6,8522 gold badges34 silver badges38 bronze badges

answered Aug 23, 2016 at 16:37

Abdennour TOUMI's user avatar

Abdennour TOUMIAbdennour TOUMI

85.4k38 gold badges243 silver badges250 bronze badges

9

For big arrays (~10⁷ elements), Math.min and Math.max both produces the following error in Node.js.

RangeError: Maximum call stack size exceeded

A more robust solution is to not add every element to the call stack, but to instead pass an array:

function arrayMin(arr) {
  return arr.reduce(function (p, v) {
    return ( p < v ? p : v );
  });
}

function arrayMax(arr) {
  return arr.reduce(function (p, v) {
    return ( p > v ? p : v );
  });
}

If you are concerned about speed, the following code is ~3 times faster then Math.max.apply is on my computer. See https://jsben.ch/JPOyL.

function arrayMin(arr) {
  var len = arr.length, min = Infinity;
  while (len--) {
    if (arr[len] < min) {
      min = arr[len];
    }
  }
  return min;
};

function arrayMax(arr) {
  var len = arr.length, max = -Infinity;
  while (len--) {
    if (arr[len] > max) {
      max = arr[len];
    }
  }
  return max;
};

If your arrays contains strings instead of numbers, you also need to coerce them into numbers. The below code does that, but it slows the code down ~10 times on my machine. See https://jsben.ch/uPipD.

function arrayMin(arr) {
  var len = arr.length, min = Infinity;
  while (len--) {
    if (Number(arr[len]) < min) {
      min = Number(arr[len]);
    }
  }
  return min;
};

function arrayMax(arr) {
  var len = arr.length, max = -Infinity;
  while (len--) {
    if (Number(arr[len]) > max) {
      max = Number(arr[len]);
    }
  }
  return max;
};

EscapeNetscape's user avatar

answered Nov 18, 2012 at 14:00

Linus Unnebäck's user avatar

Linus UnnebäckLinus Unnebäck

22.6k14 gold badges73 silver badges89 bronze badges

6

tl;dr

// For regular arrays:
var max = Math.max(...arrayOfNumbers);

// For arrays with tens of thousands of items:
let max = testArray[0];
for (let i = 1; i < testArrayLength; ++i) {
  if (testArray[i] > max) {
    max = testArray[i];
  }
}

MDN solution

The official MDN docs on Math.max() already covers this issue:

The following function uses Function.prototype.apply() to find the maximum element in a numeric array. getMaxOfArray([1, 2, 3]) is equivalent to Math.max(1, 2, 3), but you can use getMaxOfArray() on programmatically constructed arrays of any size.

function getMaxOfArray(numArray) {
    return Math.max.apply(null, numArray);
}

Or with the new spread operator, getting the maximum of an array becomes a lot easier.

var arr = [1, 2, 3];
var max = Math.max(...arr);

Maximum size of an array

According to MDN the apply and spread solutions had a limitation of 65536 that came from the limit of the maximum number of arguments:

But beware: in using apply this way, you run the risk of exceeding the JavaScript engine’s argument length limit. The consequences of applying a function with too many arguments (think more than tens of thousands of arguments) vary across engines (JavaScriptCore has hard-coded argument limit of 65536), because the limit (indeed even the nature of any excessively-large-stack behavior) is unspecified. Some engines will throw an exception. More perniciously, others will arbitrarily limit the number of arguments actually passed to the applied function. To illustrate this latter case: if such an engine had a limit of four arguments (actual limits are of course significantly higher), it would be as if the arguments 5, 6, 2, 3 had been passed to apply in the examples above, rather than the full array.

They even provide a hybrid solution which doesn’t really have good performance compared to other solutions. See performance test below for more.

In 2019 the actual limit is the maximum size of the call stack. For modern Chromium based desktop browsers this means that when it comes to finding min/max with apply or spread, practically the maximum size for numbers only arrays is ~120000. Above this, there will be a stack overflow and the following error will be thrown:

RangeError: Maximum call stack size exceeded

With the script below (based on this blog post), by catching that error you can calculate the limit for your specific environment.

Warning! Running this script takes time and depending on the performance of your system it might slow or crash your browser/system!

let testArray = Array.from({length: 10000}, () => Math.floor(Math.random() * 2000000));
for (i = 10000; i < 1000000; ++i) {
  testArray.push(Math.floor(Math.random() * 2000000));
  try {
    Math.max.apply(null, testArray);
  } catch (e) {
    console.log(i);
    break;
  }
}

Performance on large arrays

Based on the test in EscapeNetscape’s comment I created some benchmarks that tests 5 different methods on a random number only array with 100000 items.

In 2019, the results show that the standard loop (which BTW doesn’t have the size limitation) is the fastest everywhere. apply and spread comes closely after it, then much later MDN’s hybrid solution then reduce as the slowest.

Almost all tests gave the same results, except for one where spread somewhy ended up being the slowest.

If you step up your array to have 1 million items, things start to break and you are left with the standard loop as a fast solution and reduce as a slower.

JSPerf benchmark

jsperf.com benchmark results for different solutions to find the min/max item of an array

JSBen benchmark

jsben.com benchmark results for different solutions to find the min/max item of an array

JSBench.me benchmark

jsbench.me benchmark results for different solutions to find the min/max item of an array

Benchmark source code

answered Jun 14, 2015 at 21:22

totymedli's user avatar

totymedlitotymedli

29k22 gold badges130 silver badges163 bronze badges

4

If you’re paranoid like me about using Math.max.apply (which could cause errors when given large arrays according to MDN), try this:

function arrayMax(array) {
  return array.reduce(function(a, b) {
    return Math.max(a, b);
  });
}

function arrayMin(array) {
  return array.reduce(function(a, b) {
    return Math.min(a, b);
  });
}

Or, in ES6:

function arrayMax(array) {
  return array.reduce((a, b) => Math.max(a, b));
}

function arrayMin(array) {
  return array.reduce((a, b) => Math.min(a, b));
}

The anonymous functions are unfortunately necessary (instead of using Math.max.bind(Math) because reduce doesn’t just pass a and b to its function, but also i and a reference to the array itself, so we have to ensure we don’t try to call max on those as well.

answered Jul 27, 2015 at 1:00

Daniel Buckmaster's user avatar

7

Alternative Methods


The Math.min and Math.max are great methods to get the minimum and maximum item out of a collection of items, however it’s important to be aware of some cavities that can comes with it.

Using them with an array that contains large number of items (more than ~10⁷ items, depends on the user’s browser) most likely will crash and give the following error message:

const arr = Array.from(Array(1000000).keys());
Math.min(arr);
Math.max(arr);

Uncaught RangeError: Maximum call stack size exceeded

UPDATE
Latest browsers might return NaN instead. That might be a better way to handle errors, however it doesn’t solve the problem just yet.

Instead, consider using something like so:

function maxValue(arr) {
  return arr.reduce((max, val) => max > val ? max : val)
}

Or with better run-time:

function maxValue(arr) {
  let max = arr[0];

  for (let val of arr) {
    if (val > max) {
      max = val;
    }
  }
  return max;
}

Or to get both Min and Max:

function getMinMax(arr) {
  return arr.reduce(({min, max}, v) => ({
    min: min < v ? min : v,
    max: max > v ? max : v,
  }), { min: arr[0], max: arr[0] });
}

Or with even better run-time*:

function getMinMax(arr) {
  let min = arr[0];
  let max = arr[0];
  let i = arr.length;
    
  while (i--) {
    min = arr[i] < min ? arr[i] : min;
    max = arr[i] > max ? arr[i] : max;
  }
  return { min, max };
}

* Tested with 1,000,000 items:
Just for a reference, the 1st function run-time (on my machine) was 15.84ms vs 2nd function with only 4.32ms.

answered Oct 2, 2018 at 17:34

Lior Elrom's user avatar

Lior ElromLior Elrom

19.4k16 gold badges80 silver badges92 bronze badges

3

Two ways are shorter and easy:

let arr = [2, 6, 1, 0]

Way 1:

let max = Math.max.apply(null, arr)

Way 2:

let max = arr.reduce(function(a, b) {
    return Math.max(a, b);
});

answered May 18, 2018 at 1:37

Hafizur Rahman's user avatar

3

.apply is often used when the intention is to invoke a variadic function with a list of argument values, e.g.

The Math.max([value1[,value2, ...]]) function returns the largest of zero or more numbers.

Math.max(10, 20); // 20
Math.max(-10, -20); // -10
Math.max(-10, 20); // 20

The Math.max() method doesn’t allow you to pass in an array. If you have a list of values of which you need to get the largest, you would normally call this function using Function.prototype.apply(), e.g.

Math.max.apply(null, [10, 20]); // 20
Math.max.apply(null, [-10, -20]); // -10
Math.max.apply(null, [-10, 20]); // 20

However, as of the ECMAScript 6 you can use the spread operator:

The spread operator allows an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) are expected.

Using the spread operator, the above can be rewritten as such:

Math.max(...[10, 20]); // 20
Math.max(...[-10, -20]); // -10
Math.max(...[-10, 20]); // 20

When calling a function using the variadic operator, you can even add additional values, e.g.

Math.max(...[10, 20], 50); // 50
Math.max(...[-10, -20], 50); // 50

Bonus:

Spread operator enables you to use the array literal syntax to create new arrays in situations where in ES5 you would need to fall back to imperative code, using a combination of push, splice, etc.

let foo = ['b', 'c'];
let bar = ['a', ...foo, 'd', 'e']; // ['a', 'b', 'c', 'd', 'e']

answered Dec 18, 2014 at 1:38

Gajus's user avatar

GajusGajus

67.9k70 gold badges271 silver badges435 bronze badges

1

You do it by extending the Array type:

Array.max = function( array ){
    return Math.max.apply( Math, array );
};
Array.min = function( array ){
    return Math.min.apply( Math, array );
}; 

Boosted from here (by John Resig)

answered Nov 3, 2009 at 18:35

brettkelly's user avatar

brettkellybrettkelly

27.6k8 gold badges56 silver badges71 bronze badges

A simple solution to find the minimum value over an Array of elements is to use the Array prototype function reduce:

A = [4,3,-9,-2,2,1];
A.reduce((min, val) => val < min ? val : min, A[0]); // returns -9

or using JavaScript’s built-in Math.Min() function (thanks @Tenflex):

A.reduce((min,val) => Math.min(min,val), A[0]);

This sets min to A[0], and then checks for A[1]...A[n] whether it is strictly less than the current min. If A[i] < min then min is updated to A[i]. When all array elements has been processed, min is returned as the result.

EDIT: Include position of minimum value:

A = [4,3,-9,-2,2,1];
A.reduce((min, val) => val < min._min ? {_min: val, _idx: min._curr, _curr: min._curr + 1} : {_min: min._min, _idx: min._idx, _curr: min._curr + 1}, {_min: A[0], _idx: 0, _curr: 0}); // returns { _min: -9, _idx: 2, _curr: 6 }

answered Oct 29, 2017 at 11:26

Nicolas Lykke Iversen's user avatar

2

For a concise, modern solution, one can perform a reduce operation over the array, keeping track of the current minimum and maximum values, so the array is only iterated over once (which is optimal). Destructuring assignment is used here for succinctness.

let array = [100, 0, 50];
let [min, max] = array.reduce(([prevMin,prevMax], curr)=>
   [Math.min(prevMin, curr), Math.max(prevMax, curr)], [Infinity, -Infinity]);
console.log("Min:", min);
console.log("Max:", max);

To only find either the minimum or maximum, we can use perform a reduce operation in much the same way, but we only need to keep track of the previous optimal value. This method is better than using apply as it will not cause errors when the array is too large for the stack.

const arr = [-1, 9, 3, -6, 35];

//Only find minimum
const min = arr.reduce((a,b)=>Math.min(a,b), Infinity);
console.log("Min:", min);//-6

//Only find maximum
const max = arr.reduce((a,b)=>Math.max(a,b), -Infinity);
console.log("Max:", max);//35

answered Aug 20, 2020 at 22:47

Unmitigated's user avatar

UnmitigatedUnmitigated

70.4k8 gold badges58 silver badges77 bronze badges

Others have already given some solutions in which they augment Array.prototype. All I want in this answer is to clarify whether it should be Math.min.apply( Math, array ) or Math.min.apply( null, array ). So what context should be used, Math or null?

When passing null as a context to apply, then the context will default to the global object (the window object in the case of browsers). Passing the Math object as the context would be the correct solution, but it won’t hurt passing null either. Here’s an example when null might cause trouble, when decorating the Math.max function:

// decorate Math.max
(function (oldMax) {
    Math.max = function () {
        this.foo(); // call Math.foo, or at least that's what we want

        return oldMax.apply(this, arguments);
    };
})(Math.max);

Math.foo = function () {
    print("foo");
};

Array.prototype.max = function() {
  return Math.max.apply(null, this); // <-- passing null as the context
};

var max = [1, 2, 3].max();

print(max);

The above will throw an exception because this.foo will be evaluated as window.foo, which is undefined. If we replace null with Math, things will work as expected and the string “foo” will be printed to the screen (I tested this using Mozilla Rhino).

You can pretty much assume that nobody has decorated Math.max so, passing null will work without problems.

answered Nov 3, 2009 at 18:39

Ionuț G. Stan's user avatar

Ionuț G. StanIonuț G. Stan

175k18 gold badges188 silver badges202 bronze badges

2

One more way to do it:

var arrayMax = Function.prototype.apply.bind(Math.max, null);

Usage:

var max = arrayMax([2, 5, 1]);

gion_13's user avatar

gion_13

41k10 gold badges95 silver badges107 bronze badges

answered Sep 26, 2012 at 18:43

sbr's user avatar

sbrsbr

4,6955 gold badges42 silver badges48 bronze badges

2

I am surprised not one mentiond the reduce function.

var arr = [1, 10, 5, 11, 2]

var b = arr.reduce(function(previous,current){ 
                      return previous > current ? previous:current
                   });

b => 11
arr => [1, 10, 5, 11, 2]

2

This may suit your purposes.

Array.prototype.min = function(comparer) {

    if (this.length === 0) return null;
    if (this.length === 1) return this[0];

    comparer = (comparer || Math.min);

    var v = this[0];
    for (var i = 1; i < this.length; i++) {
        v = comparer(this[i], v);    
    }

    return v;
}

Array.prototype.max = function(comparer) {

    if (this.length === 0) return null;
    if (this.length === 1) return this[0];

    comparer = (comparer || Math.max);

    var v = this[0];
    for (var i = 1; i < this.length; i++) {
        v = comparer(this[i], v);    
    }

    return v;
}

answered Nov 3, 2009 at 18:21

ChaosPandion's user avatar

ChaosPandionChaosPandion

77.2k18 gold badges118 silver badges156 bronze badges

5

let array = [267, 306, 108]
let longest = Math.max(…array);

answered Oct 3, 2020 at 15:10

Trilok Singh's user avatar

Trilok SinghTrilok Singh

1,17712 silver badges9 bronze badges

1

I thought I’d share my simple and easy to understand solution.

For the min:

var arr = [3, 4, 12, 1, 0, 5];
var min = arr[0];
for (var k = 1; k < arr.length; k++) {
  if (arr[k] < min) {
    min = arr[k];
  }
}
console.log("Min is: " + min);

And for the max:

var arr = [3, 4, 12, 1, 0, 5];
var max = arr[0];
for (var k = 1; k < arr.length; k++) {
  if (arr[k] > max) {
    max = arr[k];
  }
}
console.log("Max is: " + max);

answered Oct 13, 2016 at 16:37

Ionut Necula's user avatar

Ionut NeculaIonut Necula

11k4 gold badges45 silver badges69 bronze badges

9

For big arrays (~10⁷ elements), Math.min and Math.max procuces a RangeError (Maximum call stack size exceeded) in node.js.

For big arrays, a quick & dirty solution is:

Array.prototype.min = function() {
    var r = this[0];
    this.forEach(function(v,i,a){if (v<r) r=v;});
    return r;
};

answered Jan 24, 2012 at 12:43

Peter's user avatar

PeterPeter

5,0985 gold badges29 silver badges38 bronze badges

array.sort((a, b) => b - a)[0];

Gives you the maximum value in an array of numbers.

array.sort((a, b) => a - b)[0];

Gives you the minimum value in an array of numbers.

let array = [0,20,45,85,41,5,7,85,90,111];

let maximum = array.sort((a, b) => b - a)[0];
let minimum = array.sort((a, b) => a - b)[0];

console.log(minimum, maximum)

answered Jun 20, 2020 at 20:33

Adam Beleko's user avatar

Adam BelekoAdam Beleko

6387 silver badges15 bronze badges

For an array containing objects instead of numbers:

arr = [
  { name: 'a', value: 5 },
  { name: 'b', value: 3 },
  { name: 'c', value: 4 }
]

You can use reduce to get the element with the smallest value (min)

arr.reduce((a, b) => a.value < b.value ? a : b)
// { name: 'b', value: 3 }

or the largest value (max)

arr.reduce((a, b) => a.value > b.value ? a : b)
// { name: 'a', value: 5 }

answered Aug 6, 2020 at 12:17

laktak's user avatar

laktaklaktak

56.2k17 gold badges134 silver badges164 bronze badges

Aside using the math function max and min, another function to use is the built in function of sort(): here we go

const nums = [12, 67, 58, 30].sort((x, y) => 
x -  y)
let min_val = nums[0]
let max_val = nums[nums.length -1]

black.swordsman's user avatar

answered Feb 14, 2020 at 15:29

Chukwuemeka Maduekwe's user avatar

1

I had the same problem, I needed to obtain the minimum and maximum values of an array and, to my surprise, there were no built-in functions for arrays. After reading a lot, I decided to test the “top 3” solutions myself:

  1. discrete solution: a FOR loop to check every element of the array against the current max and/or min value;
  2. APPLY solution: sending the array to the Math.max and/or Math.min internal functions using apply(null,array);
  3. REDUCE solution: recursing a check against every element of the array using reduce(function).

The test code was this:

function GetMaxDISCRETE(A)
{   var MaxX=A[0];

    for (var X=0;X<A.length;X++)
        if (MaxX<A[X])
            MaxX=A[X];

    return MaxX;
}

function GetMaxAPPLY(A)
{   return Math.max.apply(null,A);
}

function GetMaxREDUCE(A)
{   return A.reduce(function(p,c)
    {   return p>c?p:c;
    });
}

The array A was filled with 100,000 random integer numbers, each function was executed 10,000 times on Mozilla Firefox 28.0 on an intel Pentium 4 2.99GHz desktop with Windows Vista. The times are in seconds, retrieved by performance.now() function. The results were these, with 3 fractional digits and standard deviation:

  1. Discrete solution: mean=0.161s, sd=0.078
  2. APPLY solution: mean=3.571s, sd=0.487
  3. REDUCE solution: mean=0.350s, sd=0.044

The REDUCE solution was 117% slower than the discrete solution. The APPLY solution was the worse, 2,118% slower than the discrete solution. Besides, as Peter observed, it doesn’t work for large arrays (about more than 1,000,000 elements).

Also, to complete the tests, I tested this extended discrete code:

var MaxX=A[0],MinX=A[0];

for (var X=0;X<A.length;X++)
{   if (MaxX<A[X])
        MaxX=A[X];
    if (MinX>A[X])
        MinX=A[X];
}

The timing: mean=0.218s, sd=0.094

So, it is 35% slower than the simple discrete solution, but it retrieves both the maximum and the minimum values at once (any other solution would take at least twice that to retrieve them). Once the OP needed both values, the discrete solution would be the best choice (even as two separate functions, one for calculating maximum and another for calculating minimum, they would outperform the second best, the REDUCE solution).

answered Apr 2, 2014 at 17:46

Cyberknight's user avatar

CyberknightCyberknight

1562 silver badges6 bronze badges

Iterate through, keeping track as you go.

var min = null;
var max = null;
for (var i = 0, len = arr.length; i < len; ++i)
{
    var elem = arr[i];
    if (min === null || min > elem) min = elem;
    if (max === null || max < elem) max = elem;
}
alert( "min = " + min + ", max = " + max );

This will leave min/max null if there are no elements in the array. Will set min and max in one pass if the array has any elements.

You could also extend Array with a range method using the above to allow reuse and improve on readability. See a working fiddle at http://jsfiddle.net/9C9fU/

Array.prototype.range = function() {

    var min = null,
        max = null,
        i, len;

    for (i = 0, len = this.length; i < len; ++i)
    {
        var elem = this[i];
        if (min === null || min > elem) min = elem;
        if (max === null || max < elem) max = elem;
    }

    return { min: min, max: max }
};

Used as

var arr = [3, 9, 22, -7, 44, 18, 7, 9, 15];

var range = arr.range();

console.log(range.min);
console.log(range.max);

answered Nov 3, 2009 at 18:23

tvanfosson's user avatar

tvanfossontvanfosson

522k99 gold badges697 silver badges794 bronze badges

1

You can use the following function anywhere in your project:

function getMin(array){
    return Math.min.apply(Math,array);
}

function getMax(array){
    return Math.max.apply(Math,array);
}

And then you can call the functions passing the array:

var myArray = [1,2,3,4,5,6,7];
var maximo = getMax(myArray); //return the highest number

falsarella's user avatar

falsarella

12.2k9 gold badges69 silver badges115 bronze badges

answered Aug 26, 2014 at 16:57

Max Cabrera's user avatar

The following code works for me :

var valueList = [10,4,17,9,3];
var maxValue = valueList.reduce(function(a, b) { return Math.max(a, b); });
var minValue = valueList.reduce(function(a, b) { return Math.min(a, b); });

Gogol's user avatar

Gogol

3,0334 gold badges28 silver badges57 bronze badges

answered May 26, 2017 at 12:40

jaydip jadhav's user avatar

0

let arr=[20,8,29,76,7,21,9]
Math.max.apply( Math, arr ); // 76

answered Oct 28, 2020 at 21:53

Shashwat Gupta's user avatar

Simple stuff, really.

var arr = [10,20,30,40];
arr.max = function() { return  Math.max.apply(Math, this); }; //attach max funct
arr.min = function() { return  Math.min.apply(Math, this); }; //attach min funct

alert("min: " + arr.min() + " max: " + arr.max());

falsarella's user avatar

falsarella

12.2k9 gold badges69 silver badges115 bronze badges

answered Sep 23, 2014 at 7:48

Brian's user avatar

BrianBrian

3,6431 gold badge22 silver badges33 bronze badges

Here’s one way to get the max value from an array of objects. Create a copy (with slice), then sort the copy in descending order and grab the first item.

var myArray = [
    {"ID": 1, "Cost": 200},
    {"ID": 2, "Cost": 1000},
    {"ID": 3, "Cost": 50},
    {"ID": 4, "Cost": 500}
]

maxsort = myArray.slice(0).sort(function(a, b) { return b.ID - a.ID })[0].ID; 

falsarella's user avatar

falsarella

12.2k9 gold badges69 silver badges115 bronze badges

answered Jan 9, 2014 at 18:46

Ben's user avatar

BenBen

5849 silver badges8 bronze badges

title slug page-type browser-compat

Math.max()

Web/JavaScript/Reference/Global_Objects/Math/max

javascript-static-method

javascript.builtins.Math.max

{{JSRef}}

The Math.max() static method returns the largest of the numbers given as input parameters, or -{{jsxref(“Infinity”)}} if there are no parameters.

{{EmbedInteractiveExample(“pages/js/math-max.html”)}}

Syntax

Math.max()
Math.max(value0)
Math.max(value0, value1)
Math.max(value0, value1, /* … ,*/ valueN)

Parameters

  • value1, value2, … , valueN
    • : Zero or more numbers among which the largest value will be selected and returned.

Return value

The largest of the given numbers. Returns {{jsxref(“NaN”)}} if any of the parameters is or is converted into NaN. Returns -{{jsxref(“Infinity”)}} if no parameters are provided.

Description

Because max() is a static method of Math, you always use it as Math.max(), rather than as a method of a Math object you created (Math is not a constructor).

Math.max.length is 2, which weakly signals that it’s designed to handle at least two parameters.

Examples

Using Math.max()

Math.max(10, 20); // 20
Math.max(-10, -20); // -10
Math.max(-10, 20); // 20

Getting the maximum element of an array

{{jsxref(“Array.prototype.reduce()”)}} can be used to find the maximum
element in a numeric array, by comparing each value:

const arr = [1, 2, 3];
const max = arr.reduce((a, b) => Math.max(a, b), -Infinity);

The following function uses {{jsxref(“Function.prototype.apply()”)}} to get the maximum of an array. getMaxOfArray([1, 2, 3]) is equivalent to Math.max(1, 2, 3), but you can use getMaxOfArray() on programmatically constructed arrays. This should only be used for arrays with relatively few elements.

function getMaxOfArray(numArray) {
  return Math.max.apply(null, numArray);
}

The spread syntax is a shorter way of writing the apply solution to get the maximum of an array:

const arr = [1, 2, 3];
const max = Math.max(...arr);

However, both spread (...) and apply will either fail or return the wrong result if the array has too many elements, because they try to pass the array elements as function parameters. See Using apply and built-in functions for more details. The reduce solution does not have this problem.

Specifications

{{Specifications}}

Browser compatibility

{{Compat}}

See also

  • {{jsxref(“Math.min()”)}}

JavaScript Math

Определение и применение

JavaScript метод max() объекта Math позволяет найти и возвратить наибольшее из переданных чисел.

Обращаю Ваше внимание на то, что если хотя бы один из переданных параметров не может быть преобразован в число, то результатом вызова метода будет значение NaN.

Если метод max() вызывается без параметров, то в качестве возвращаемого значения возвращается значение -Infinity.

Поддержка браузерами

JavaScript синтаксис:

Math.max( value1, value2, ...valueX ); 

value - Number

Версия JavaScript

1.0 (ECMAScript 1st Edition)

Значения параметров

Параметр Описание
value1, value2, …valueX Числовые значения.

Пример использования

Базовое использование

const a = 5,
      b = -12,
      c = 20;

// находим минимальное число из переданных значений
Math.min(a, b, c); // возвращаемое значение 5

// находим максимальное число из переданных значений
Math.max(a, b, c); // возвращаемое значение 20

Обрезание значения

В следующем примере мы рассмотрим как с помощью методов min() и max() объекта Math обрезать значение по верхней или нижней границе, если оно превышает или меньше определенного значения:

const a = someFunc(num);

// условие без использования метода min
if (a > boundary) {
  a = boundary;
}

// перепишем условие с помощью метода min
const val = Math.min(a, boundary); // если значение параметра a будет больше значения парметра boundary, то будет выбрано значение параметра boundary

const b = someFunc(num);

// условие без использования метода max
if (b < boundary) {
  b = boundary;
}

// перепишем условие с помощью метода max
const b = Math.max(b, boundary); // если значение параметра b будет меньше значения парметра boundary, то будет выбрано значение параметра boundary

Минимальное и максимальное значение в массиве

В следующем примере мы рассмотрим как с помощью методов min() и max() объекта Math найти минимальное и максимальное значение внутри массива.

// инициализируем переменную, содержащую массив
const arr = [-10, 22, 5, -2];

// находим минимальное число в массиве
Math.min.apply( null, arr ); // возвращаемое значение -10

// находим максимальное число в массиве
Math.max.apply( null, arr ); // возвращаемое значение 22

// тоже самое с помощью спред оператора ES2015

Math.min(...arr); // возвращаемое значение -10
Math.max(...arr); // возвращаемое значение 22

Обратите внимание, что в первом случае был использован метод apply() объекта Function.

JavaScript Math

Для того, чтобы найти максимальный элемент в массиве, можно воспользоваться не только агрегацией. Давайте обратимся к стандартным возможностям языка и рассмотрим метод Math.max.apply():

const numbers = [-94, 87, 12, 0, -67, 32];
const maxValue = Math.max.apply(null, numbers);
//обратите внимание, что в записи данного метода обязателен null. 
//Если забыть в записи данного выражения null, то в переменную maxValue вернётся -Infinity.
console.log(maxValue); // => 87

Есть ещё более хитрый способ использовать метод Math.max():
Для этого вспомним про spread оператор.

const numbers = [-94, 87, 12, 0, -67, 32];
const maxValue = Math.max(...numbers);
console.log(maxValue); // => 87

И невозможно не упомянуть про библиотеку Lodash с методом _.max():

const numbers = [-94, 87, 12, 0, -67, 32];
const maxValue = _.max(numbers);
console.log(maxValue); // => 87

Документация:

  • Math.max.apply()
  • _.max()

In core javaScript there is the Math max and Math min methods that can be used to find the highest and lowest numbers in a set of numbers. The methods work by passing the set of numbers as arguments, but it is also possible to use an array by making use of the apply function prototype method. The apply method can be called off of the Math.max or min method as it is a function prototype method, and then a null value can be given as the first argument, along with the array of numbers, more on that later.

The Math min and max methods can help save me from having to loop over the contents of an array to find the lowest or highest number in a array of numbers. The task of doing this does come up now and then when working out solutions for certain things that require the lowest and highest numbers in a collection of numbers. So lets take a look at some some examples, and a few additional use case examples of Math min and max.

1 – Math min and Max basics

In this section I will be going over a few basic examples of the Math.min, and Math max methods in the Math object of core javaScript. I will also be touching base on any and all other related topics in this basic section before getting into more advanced topics and any and all simple project examples. I will be keeping these example fairly simple but this is still not a post on making the first few steps when getting started with javaScriot, so I assume that you have at least some background with javaScript before hand.

– The source code examples here are on Github

The source code examples that I am writing about in this post can be found in my test vjs repository on Git hub along with the source code examples for all my other posts on native javaScript.

1.1 – Basic Math min example

The Math min and Math max methods work by passing numbers as arguments to the methods and then the smallest or largest number that is passed is returned by the method. So if I give the Math min method the numbers 3, 0, and -7 as arguments then the number -7 is what will be returned.

1

2

var min = Math.min(3, 0, -7);

console.log(min);

Although this simple example works out okay for what it is, when it comes to any kind of real code example such code examples will often involve an array of values, and likely never a set of static number literals. So lets look at some more examples of using these methods to get the lowest and highest numbers in a collection of numbers in javaScript.

1.2 – Using the apply function prototype method

If you are not familiar with the function apply prototype method yet as well as other such methods such as call and bind, now would be a good time to look into them. I will not be getting into these methods in depth here as I have written a post before hand in which I do so. However here is a simple example if using the apply function prototype method with Math min and max to get the lowest and highest numbers in an array of numbers.

1

2

3

4

5

var nums = [7, -4, 0, 8, 12, -2];

console.log( Math.min.apply(null, nums) );

console.log( Math.max.apply(null, nums) );

1.3 – Array reduce method example

Of course there are a wide range of other ways to go about getting the min and max number in a series of numbers. I would say that the trick of using the apply function prototype method with the Math.min and Math.max methods is a nice quick way of doing so. However for this basic example I am going to start going over at least one if not more alternative ways of doing this sort of thing just for the heck of it. With that aid in this example I am also getting the min and max numbers in an array of numbers but I am using the Array reduce method as a means to do so.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

var arr = [1, 7, 3, -2];

var min = arr.reduce(function (acc, n) {

if (n < acc) {

return n

}

return acc;

}, Infinity);

var max = arr.reduce(function (acc, n) {

if (n > acc) {

return n

}

return acc;

}, -Infinity);

console.log(min, max);

So there are many things than can be done with a set of numbers of course. However with the Math min and max methods one of the most common typical use case examples is to get the range of a set of numbers. For convenience in this section I will also be going over some examples of sum, mean, and median in this section also.

2.1 – Get the range of a set of numbers

So making a get range method with Math min, and Math max would involve just using the methods along with function apply to get the min and max numbers of a set of numbers. Then I just need to have the function return the max number less the min number. The returned result of the method would then be the range.

1

2

3

4

5

6

7

8

var getRange = function (nums) {

var min = Math.min.apply(null, nums),

max = Math.max.apply(null, nums);

return max - min;

};

var arr = [-5, 10, 8, 3, 0];

console.log(getRange(arr));

Getting the range of a set of numbers if often just one step in getting some other value. For example say that I want an array of numbers between the range of 320, based off of values of an array of numbers that are of a lower or higher range. I can use the range to loop over the source array of numbers and divide each value by the range of the source array, then multiply by 320 to get those values.

So the range of a set of numbers is often just one value of interest along with a bunch of other typical values such as mean, median, and sum. There is having just one of these methods in a stand alone state of sorts, and then there is making what might be the beginnings of a utility library of sorts. For now lets just start out with some stand alone methods for all of these. I can then have a single method that will return an object that will give me everything there is that I would want with an array of numbers ore or less when it comes to just these few things at least.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

var getMedian = function (nums) {

var half = Math.floor(nums.length / 2);

nums.sort();

return nums.length % 2 ? nums[half] : (nums[half - 1] + nums[half]) / 2;

};

var getSum = function (nums) {

var i = nums.length,

sum = 0;

while (i--) {

sum += nums[i];

}

return sum;

};

var getMean = function (nums) {

return getSum(nums) / nums.length;

};

var getEverything = function (nums) {

var e = {};

e.min = Math.min.apply(null, nums);

e.max = Math.max.apply(null, nums);

e.range = getRange(nums);

e.median = getMedian(nums);

e.sum = getSum(nums);

e.mean = getMean(nums);

return e;

};

var nums = [1, 2, 4, 7];

var e = getEverything(nums);

console.log(e.median);

console.log(e.min, e.max);

console.log(e.range);

console.log(e.sum);

console.log(e.mean);

There is more than one way to go about making a sum method, in this example I used a while loop to just loop over and add up the numbers. Other solutions might involve the use of the array reduce method, however getting into that might be off topic here. The thing about this is that I have a method that will give me all the basics when it comes to things of interest with a set of numbers, but not everything.

One additional thing is to have a normalized set of numbers for the array of numbers, so lets look at an example of that. In addition it might be nice to get into some actual examples that make use of all of this to do something interesting, so lets start getting into the good stuff with this.

3 – Number normalization example of Math.min and Math.max

One use case example of Math.min and Math.max might be to make a method that is used to normalize numbers relative to a range between the min and max number. This sort of thing is often used as a way to normalize points for example so they can then easy be scaled up by just multiplying the normalized value by a scale.

This can be done by using the Math.min method to get the lowest number, then Math.Max to get the highest, and with that the range of course. Once I have the range I can then use the array map method to map over the array of numbers and create and return a new array where each value is divided over the range.

1

2

3

4

5

6

7

8

9

10

11

12

var normalizeNums = function (nums) {

var min = Math.min.apply(null, nums),

max = Math.max.apply(null, nums),

range = max - min;

return nums.map(function (n) {

return n / range;

});

};

var nums = [-37, 5, 42, 30, 43, 120, -40, 160];

console.log( normalizeNums(nums) );

4 – Working with an array of Objects

So now that we have figures out how to go about normalizing a set of numbers, lets see about working with an array of objects Say I have an array of points in the form of an array of objects where each object has an x and y property. I want to get the lowest and highest values for each axis in the set of points. For this one again the array map method can come in handy for getting all values of interest with that.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

var getAxisValues = function (points, axis) {

axis = axis === undefined ? 'x' : axis;

return points.map(function (obj) {

return obj[axis];

});

};

var getLorHofAxis = function (points, axis, minMax) {

axis = axis === undefined ? 'x' : axis;

minMax = minMax === undefined ? 'min' : minMax;

return Math[minMax].apply(null, getAxisValues(points, axis));

};

var points = [{x: 20, y: 35},{x: -15, y: 83},{x: 7, y: 0}],

xLow = getLorHofAxis(points),

yHi = getLorHofAxis(points, 'y', 'max');

console.log(xLow);

console.log(yHi);

5 – Canvas example using Math.max, and Math.min

So maybe now it is time for a canvas example that makes use of the Math.max, and Math.min methods, along with everything else this I covered in this post and much more.

This canvas example will have a point.js module that will contain methods for generating and array of points. In addition it will have methods that make use of Math.max, and Math.min to help find the highest and lowest axis values for the x and y axis values of all the points. It will contain a while bunch of other methods that will help illustrate the was covered in this post when using it in a canvas example.

5.1 – The points.js module

So here is the points.js module that will be used to create the array of points. There are also a number of other public api methods for this module including a methods that is used to move an array of points, and also a methods that can be used to create a point object composed of the lowest x and y values that of course make use of Math.min, and Math.max.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

var points = (function () {

var api = {};

api.gen = function (count, width, height) {

count = count === undefined ? 10 : count;

width = width === undefined ? 160 : width;

height = height === undefined ? 120 : height;

var points = [];

var i = 0;

while (i < count) {

points.push({

x: Math.floor(Math.random() * width),

y: Math.floor(Math.random() * height),

heading: Math.random() * (Math.PI * 2),

pps: 16 + Math.round(64 * Math.random())

})

i += 1;

}

return points;

};

var getAxisValues = function (points, axis) {

axis = axis === undefined ? 'x' : axis;

return points.map(function (obj) {

return obj[axis];

});

};

api.getLorH = function (points, minMax) {

minMax = minMax === undefined ? 'min' : minMax;

return {

x: Math[minMax].apply(null, getAxisValues(points, 'x')),

y: Math[minMax].apply(null, getAxisValues(points, 'y'))

}

};

api.getAxisRanges = function (points) {

var xValues = getAxisValues(points, 'x'),

yValues = getAxisValues(points, 'y'),

xLow = Math.min.apply(null, xValues),

yLow = Math.min.apply(null, yValues);

return {

x: (Math.max.apply(null, xValues) - Math.abs(xLow)),

y: (Math.max.apply(null, yValues) - Math.abs(yLow))

}

};

var normalize = function (points, canvas) {

var range = api.getAxisRanges(points);

canvas = canvas || {

width: range.x,

height: range.y

};

return points.map(function (pt) {

return {

x: pt.x / canvas.width,

y: pt.y / canvas.height

}

});

};

api.move = function (points, x, y, w, h, canvas) {

return normalize(points, canvas).map(function (pt) {

return {

x: x + pt.x * w,

y: y + pt.y * h

};

});

};

api.wrap = function (points, canvas) {

return points.map(function (pt) {

var x = pt.x,

y = pt.y;

x = x < 0 ? canvas.width + x : x;

y = y < 0 ? canvas.height + y : y;

x = x >= 320 ? x % 320 : x;

y = y >= 240 ? y % 240 : y;

return {

x: x,

y: y,

heading: pt.heading,

pps: pt.pps

}

});

};

return api;

}

());

5.2 – The draw.js module for drawing to a canvas element

So as with any of my canvas examples I made a draw.js module that will contain the draw methods that will be used to serve as a view for the model in this case an array of points created with the points module. With that said there is a draw method that will draw the current state of an array of points to a drawing context, but also many others that draw the background as well as the high and low points of a points array.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

var draw = {};

draw.background = function (ctx, canvas) {

ctx.fillStyle = 'black';

ctx.fillRect(0, 0, canvas.width, canvas.height);

};

draw.box = function (ctx, x, y, w, h, fill) {

ctx.fillStyle = fill || 'black';

ctx.fillRect(x, y, w, h);

};

draw.lowAndHigh = function (ctx, p) {

ctx.strokeStyle = 'white';

var l = points.getLorH(p, 'min'),

h = points.getLorH(p, 'max');

ctx.beginPath();

ctx.arc(l.x, l.y, 3, 0, Math.PI * 2);

ctx.stroke();

ctx.beginPath();

ctx.arc(h.x, h.y, 9, 0, Math.PI * 2);

ctx.stroke();

}

draw.points = function (ctx, p, fill, radius) {

radius = radius || 6;

ctx.fillStyle = fill || 'red';

ctx.strokeStyle = 'black';

var i = p.length,

pt;

while (i--) {

pt = p[i];

ctx.beginPath();

ctx.arc(pt.x, pt.y, radius, 0, Math.PI * 2);

ctx.fill();

ctx.stroke();

}

};

5.3 – Main.js and index.html

Now I just need a main.js file that will create and inject a canvas element into the html, and make use of the points.js module and draw.js file above.

Here in the main.js file I have a state object that contains an array of points created with the generate method of the points.js module. The update method will move the points by way of there current heading and pixels per second values. The seconds value must be passed to it with the state object.

There is also a main app loop method where I am calling the update method, as well as all the draw methods that I want to use to redner the current state of the state object.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

var container = document.getElementById('canvas-min-max'),

canvas = document.createElement('canvas'),

ctx = canvas.getContext('2d');

container.appendChild(canvas);

canvas.width = 320;

canvas.height = 240;

var state = {

points: points.gen(20, canvas.width, canvas.height),

canvas: canvas,

lt: new Date(),

FPS: 16,

moved: {

x: 32,

y: 32,

w: 64,

h: 64,

points: []

}

};

var update = function (state, secs) {

var i = 0,

len = state.points.length,

pt;

while (i < len) {

pt = state.points[i];

pt.x += Math.cos(pt.heading) * pt.pps * secs;

pt.y += Math.sin(pt.heading) * pt.pps * secs;

i += 1;

}

state.points = points.wrap(state.points, state.canvas);

var m = state.moved;

m.points = points.move(state.points, m.x, m.y, m.w, m.h, state.canvas);

};

var loop = function () {

var now = new Date(),

t = now - state.lt,

secs = t / 1000;

requestAnimationFrame(loop);

if (t >= 1000 / state.FPS) {

update(state, secs);

var m = state.moved;

draw.background(ctx, canvas);

draw.points(ctx, state.points, ' green ', 6);

draw.lowAndHigh(ctx, state.points);

draw.box(ctx, m.x, m.y, m.w, m.h, ' rgba(0, 0, 255, 0.4)')

draw.points(ctx, m.points, ' blue ', 3);

draw.lowAndHigh(ctx, m.points);

state.lt = now;

}

};

loop();

Now for just a little html to tie everything together with this.

1

2

3

4

5

6

7

8

9

10

11

<html>

<head>

<title>js min max canvas app</title>

</head>

<body>

<div id="canvas-min-max"></div>

<script src="points.js"></script>

<script src="draw.js"></script>

<script src="main.js"></script>

</body>

</html>

So when this canvas example is up and running it will result in a bunch of points moving around the canvas that will wrap back ground when the go out of bounds. On top of that I am also drawing points to the canvas that are the lowest x and y positions as well as the highest.

6 – Conclusion

So the Math.min and Math.max methods re nice little methods for getting the lowest and highest value of two or more numbers. They have to be given via arguments when calling it, but apply can be sued as a way to just go ahead and use an array of numbers. There are all kinds of other values that come to mind that can then be obtained when you have both the lowest and highest numbers such as a range, or a mean.

The math object in core javaScript has a whole lot more to offer of course that is also worth looking into more at some point or another. There are methods like the math atan2 method that will come up now and then when it comes to code examples that have to do with various things in trigonometry for example.

Добавить комментарий