javascript - objects - ¿Por qué Math.min()> Math.max()?
mostrar numero mayor javascript (10)
[ECMA-262: 15.8.2.11]:
max ( [ value1 [ , value2 [ , ... ] ] ] )
Dado cero o más argumentos, llama a ToNumber en cada uno de los argumentos y devuelve el mayor de los valores resultantes.
- Si no se dan argumentos, el resultado es -∞.
- Si cualquier valor es
NaN
, el resultado esNaN
.- La comparación de valores para determinar el valor más grande se realiza como en 11.8.5, excepto que se considera que +0 es mayor que -0.
La propiedad de
length
del métodomax
es 2.
[ECMA-262: 15.8.2.12]:
min ( [ value1 [ , value2 [ , ... ] ] ] )
Dado cero o más argumentos, llama a ToNumber en cada uno de los argumentos y devuelve el más pequeño de los valores resultantes.
- Si no se dan argumentos, el resultado es + ∞.
- Si cualquier valor es
NaN
, el resultado esNaN
.- La comparación de valores para determinar el valor más pequeño se realiza como en 11.8.5, excepto que +0 se considera mayor que -0.
La propiedad de
length
del métodomin
es 2.
Sin argumentos, Math.min
es un valor que puede usar para calcular un mínimo iterativo , no un valor mínimo físico para el tipo. Lo hace siendo lo opuesto: un valor máximo físico para el tipo. (De manera similar en la otra dirección para Math.max
, y claramente +∞ < -∞
es false
) .
es decir
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];
}
}
(De hecho, puede ser simplemente que el estándar Math.min
implementación de Math.min
, ya que probablemente inicialice su resultado a + Infinity antes de hacer su trabajo en cualquier argumento presente, usando un algoritmo similar al anterior).
Por supuesto, este ejemplo es un poco artificial ya que solo pudimos escribir:
var x = Math.min(a[0], a[1], a[2], a[3], a[4]);
Sin embargo, el ciclo es útil si no conocemos la cantidad de elementos en la matriz, ya que la variante de Math.min
que está utilizando que acepta una matriz no es estándar.
Incluso entonces, puedes hacer:
var x = Math.min.apply(null, a);
// ^ reflective function-call
// ^ no object instance; function is "static"
// ^ array of arguments
Cuando escribo una matriz en el parámetro de las funciones mínimas y máximas de las matemáticas de JavaScript, devuelve el valor correcto:
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
Sin embargo, cuando uso la función sin parámetros, devuelve una respuesta incorrecta:
console.log( Math.min() ); // Infinity
console.log( Math.max() ); // -Infinity
Este devuelve falso:
console.log( Math.min() < Math.max() );
¿Por qué hace esto?
Cuando no se le dan argumentos, Math.min()
es igual a infinito y Math.max()
es -infinity
.
Esto es probablemente para garantizar que cualquier valor sea menor que el mínimo encontrado hasta el momento, y mayor que el máximo hasta el momento.
Es complicado, pero importante, decidir correctamente qué deben hacer las funciones agregadas cuando pasa el conjunto vacío.
A veces es "intuitivamente obvio": ¿cuál es la SUMA de ningún elemento? Zero, estoy seguro de que todos dirían fácilmente.
Algunas veces es menos así: ¿Cuál es el PRODUCTO de ningún elemento? Aquellos con algún entrenamiento matemático rápidamente dirán "uno", pero esto no es en absoluto obvio.
Luego llegas a MIN, MAX y ¡guau! ¿Cómo obtuvimos esos infinitos?
Una forma de decidir qué debe hacer una función agregada aquí es considerar qué comportamientos queremos que sean consistentes, incluso con conjuntos vacíos. Por ejemplo, supongamos que tenemos estos conjuntos no vacíos:
A = { 1, 2, 3 }
B = { 4, 5 }
Ahora, es cierto aquí, y de hecho para cualquier conjunto no vacío, que
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)
¿No sería agradable, dicen los matemáticos, si estas propiedades siguen siendo ciertas incluso cuando uno o ambos conjuntos están vacíos? Seguramente lo haría.
Y no mantiene este comportamiento que decide qué valor asignamos a SOME_AGGREGATE_FUNCTION(empty-set)
:
Para poder
SUM(A union B) = SUM(SUM(A), SUM(B))
para seguir siendo verdadero cuando A
está vacío y B
no, debemos tener SUM(empty-set) = 0
Para poder
PRODUCT(A union B) = PRODUCT(PRODUCT(A), PRODUCT(B))
para seguir siendo verdadero cuando A
está vacío y B
no, debemos tener PRODUCT(empty-set) = 1
Y finalmente:
Para poder
MIN(A union B) = MIN(MIN(A), MIN(B))
para seguir siendo verdadero cuando A
está vacío y B
no lo es, necesitamos MIN(empty-set)
para ser un valor que se garantiza que es mayor que cualquier valor posible en B, para que no ''interfiera con'' el resultado de MIN(B)
. Y obtenemos nuestra respuesta: MIN(empty-set) = positive infinity
Es la misma razón por la cual la suma de una lista vacía generalmente se define como 0 y su producto como 1: es el elemento de identidad de la operación. Es decir, siempre que incluya -Infinito como un elemento al calcular max, no afecta el resultado; respectivamente para Infinity y min.
Esto es sensato porque permite propiedades "asociativas" deseables para las operaciones agregadas. Por ejemplo, la suma de una lista es lo mismo que calcular las sumas de cualquier sublista (tal vez incluida la vacía) y sumarlas. Del mismo modo para productos, minutos, máximos, etc.
La idea es, matemáticamente sin ningún parámetro, que tengas un valor indefinido para el mínimo.
En cuanto a la implementación, generalmente el valor mínimo se inicializa con un valor muy grande (Infinito), que luego se actualiza a medida que se encuentran valores más pequeños. Si no se encuentra ningún valor, entonces tiene Infinity
como el valor mínimo.
El caso es opuesto al encontrar el valor máximo y es por eso que tiene -Infinity
.
No estoy seguro Pero, solo adivinando.
Recuerda cómo encontramos el min. Declare una variable con un valor extremadamente alto (Infinito) y luego pase por los valores y cada vez que encuentre un valor que sea menor que el almacenado en su variable, almacénelo como el nuevo mínimo.
Entonces, dado que no le está dando ningún valor para encontrar el valor mínimo, le da el valor inicial, es decir, Infinito.
Lo mismo para max.
Por supuesto que sí, porque el número de inicio debe ser Infinity
para Math.min
. Todos los números que sean inferiores al infinito positivo deben ser los más pequeños de una lista, si no hay más pequeños.
Y para Math.max
es lo mismo; todos los números que son más grandes que el infinito negativo deberían ser los más grandes si no hay más grandes.
Entonces, para su primer ejemplo:
Math.min(5)
donde 5
es más pequeño que el infinito positivo ( Infinity
) devolverá 5
.
Actualizar
Llamar a Math.min()
y Math.max
con un parámetro de matriz puede no funcionar en todas las plataformas. Debería hacer lo siguiente en su lugar:
Math.min.apply(null, [ 1, 2, 3, 4 , 5 ]);
Donde el primer parámetro es el argumento del alcance. Como Math.min()
y Math.max()
son funciones "estáticas", debemos establecer el argumento del alcance en nulo.
Probablemente porque la implementación inicializa una variable de comparación interna a la más alta (para Math.min) o más baja (para Math.max), antes de comenzar a comparar con las matrices vacías, y luego devuelve el valor de esta variable de comparación interna que, por supuesto, tiene no ha sido cambiado
Teóricamente, el resultado de esas funciones no se puede dar. La especificación Ecma dicta el resultado de las funciones mín. Y máx. Sin argumentos (consulte la página 163).
Obviamente, puede tener todo tipo de argumentos sobre cuál debería ser el resultado, pero de todos modos no hay una respuesta estrictamente correcta. Supongo que Ecma elige esto porque es el más fácil de implementar. Normalmente, una función máxima funciona más o menos así
result = -infinity;
foreach(arg in arguments)
if(arg > result)
result = arg;
Como puede ver, devolver -infinito cuando se llama a la función sin argumentos no requiere ningún cambio.
¿Por qué hace esto?
Porque eso es lo que dice la norma debería suceder;
15.8.2.11 max ([value1 [, value2 [, ...]]])
Dado cero o más argumentos, llama a ToNumber en cada uno de los argumentos y devuelve el mayor de los valores resultantes.
- Si no se dan argumentos, el resultado es -Infinity
- Si cualquier valor es NaN, el resultado es NaN.
- La comparación de valores para determinar el valor más grande se realiza como en 11.8.5, excepto que +0 se considera mayor que 0.
15.8.2.12 min ([value1 [, value2 [, ...]]])
Dado cero o más argumentos, llama a ToNumber en cada uno de los argumentos y devuelve el más pequeño de los valores resultantes.
- Si no se dan argumentos, el resultado es infinito.
- Si cualquier valor es NaN, el resultado es NaN.
- La comparación de valores para determinar el valor más pequeño se realiza como en 11.8.5, excepto que +0 se considera mayor que 0
PD; No es estándar que Math.max()
o Math.min()
acepte una matriz. Use Math.max(a,b,c,d,e,...)
etc. en su lugar.
En Chrome al menos;
Math.max([1,2,3,4]); // NaN