Почему Math.min ()> Math.max ()? - PullRequest
       19

Почему Math.min ()> Math.max ()?

33 голосов
/ 13 января 2012

Когда я вписываю массив в параметр математических функций минимума и максимума 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

Этот ответ возвращает ложь:

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

Почему он это делает?

Ответы [ 10 ]

45 голосов
/ 13 января 2012

Конечно, потому что стартовый номер должен быть 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() являются «статическими» функциями, мы должны установить аргумент области действия на нуль.

31 голосов
/ 13 января 2012

Сложно, но важно правильно определить, что агрегатные функции должны выполнять при пропуске пустого набора.

Иногда это «интуитивно очевидно»: что такое СУММА без элементов?Ноль, я уверен, что все с готовностью скажут.

Иногда это не так: что такое ПРОДУКТ без элементов?Те, у кого есть математическая подготовка, быстро скажут «один», но это совсем не очевидно.

Тогда вы получите МИН, МАКС и вау!Как мы получили эти бесконечности?


Один из способов решить, что должна делать агрегирующая функция, - это рассмотреть, какое поведение мы хотим сохранить согласованным даже с пустыми наборами.Например, предположим, что у нас есть эти непустые наборы:

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)

Не так лихорошо, говорят математики, если эти свойства остаются верными даже тогда, когда один или оба набора пусты?Это, безусловно, будет.

И это keepint это поведение, которое решает, какое значение мы присваиваем 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

19 голосов
/ 13 января 2012

Почему это происходит?

Потому что это то, что стандарт гласит: должно произойти;

15.8.2.11 max ([значение1 [, значение2 [,…]]])

При нулевом или большем числе аргументов вызывает ToNumber для каждого из аргументов и возвращает наибольшее из полученных значений.

  • Если аргументы не заданы, результатом будет -Infinity
  • Если любое значение равно NaN, результат равен NaN.
  • Сравнение значений для определения наибольшего значения выполняется, как в 11.8.5, за исключением того, что +0 считается большим, чем 0.

15.8.2.12 мин ([значение1 [, значение2 [,…]]])

При нулевом или большем числе аргументов вызывает ToNumber для каждого из аргументов и возвращает наименьшее из полученных значений.

  • Если аргументы не заданы, результатом будет бесконечность.
  • Если любое значение равно NaN, результат равен NaN.
  • Сравнение значений для определения наименьшего значения выполняется, как в 11.8.5, за исключением того, что считается +0 быть больше чем 0

p.s; Нестандартно, что Math.max() или Math.min() принимает массив. Вместо этого используйте Math.max(a,b,c,d,e,...) и т. Д.

По крайней мере в Chrome;

Math.max([1,2,3,4]); // NaN
14 голосов
/ 13 января 2012

Это та же самая причина, по которой сумма пустого списка обычно определяется как 0, а их произведение - как 1: это элемент идентификации операции. То есть всякий раз, когда вы включаете -Infinity в качестве элемента при вычислении max, это не влияет на результат; соответственно для бесконечности и мин.

Это разумно, поскольку позволяет использовать желательные "ассоциативные" свойства для агрегатных операций. Например, сумма списка равна вычислению сумм любых подсписков (возможно, включая пустые) и суммированию их. Аналогично для продуктов, минут, максимумов и т. Д.

10 голосов
/ 13 января 2012

[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. )

* т.е. +1061 *

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
7 голосов
/ 13 января 2012

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

3 голосов
/ 13 января 2012

Не знаю точно.Но, просто делая предположение.

Помните, как мы находим мин.Объявите переменную с очень высоким значением (бесконечность), а затем просмотрите значения, и всякий раз, когда вы найдете значение, которое меньше значения, хранящегося в вашей переменной, вы сохраните его вместо нового минимального значения.

, поскольку вы не задаете ему значения для поиска минимума, он дает вам начальное значение, т.е. бесконечность.

То же самое для макс.

0 голосов
/ 13 января 2012

Теоретически результат этих функций не может быть дан. Ecma спецификация определяет результат работы функций Min и Max без аргументов (см. Стр. 163).

Очевидно, что у вас могут быть разные аргументы о том, каким должен быть результат, но все равно нет строго правильного ответа. Я думаю, что Ecma выберет это, потому что это проще всего реализовать. Обычно функция max работает примерно так

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

Как видите, возвращение -infinity, когда функция вызывается без аргументов, вообще не требует изменений.

0 голосов
/ 13 января 2012

Идея в том, что математически без какого-либо параметра у вас фактически есть неопределенное значение для минимума.

Что касается реализации, обычно минимальное значение инициализируется очень большим значением (бесконечность), которое затем обновляется по мере нахождения меньших значений.Если значение не найдено, то у вас есть Infinity в качестве минимального значения.

Случай с поиском максимального значения противоположен, и поэтому у вас есть -Infinity.

0 голосов
/ 13 января 2012

Если не задано никаких аргументов, Math.min() равняется бесконечности, а Math.max() равно -infinity.

Это, вероятно, гарантирует, что любое значение меньше, чем найденный минимум, и больше, чем максимумпока что.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...