¿Son +0 y -0 lo mismo?
Leyendo la especificación ECMAScript 5.1 y +0
se -0
distinguen.
¿Por qué entonces se +0 === -0
evalúa a true
?
JavaScript utiliza el estándar IEEE 754 para representar números. De Wikipedia :
El cero con signo es cero con un signo asociado. En aritmética ordinaria, −0 = +0 = 0. Sin embargo, en informática, algunas representaciones numéricas permiten la existencia de dos ceros, a menudo indicados por −0 (cero negativo) y +0 (cero positivo) . Esto ocurre en algunas representaciones de números con signo para números enteros y en la mayoría de las representaciones de números de punto flotante. El número 0 normalmente se codifica como +0, pero puede representarse como +0 o −0.
El estándar IEEE 754 para aritmética de punto flotante (actualmente utilizado por la mayoría de las computadoras y lenguajes de programación que admiten números de punto flotante) requiere +0 y −0. Los ceros pueden considerarse como una variante de la recta numérica real extendida tal que 1/−0 = −∞ y 1/+0 = +∞, la división por cero solo no está definida para ±0/±0 y ±∞/±∞ .
El artículo contiene más información sobre las diferentes representaciones.
Ésta es la razón por la que, técnicamente, ambos ceros deben distinguirse.
Sin embargo,
+0 === -0
se evalúa como verdadero. Porqué es eso (...) ?
Este comportamiento se define explícitamente en la sección 11.9.6 , el Algoritmo de comparación de igualdad estricta (el énfasis es parcialmente mío):
La comparación
x === y
, dondex
yy
son valores, produce verdadero o falso . Esta comparación se realiza de la siguiente manera:(...)
Si Tipo(x) es Número, entonces
- Si x es NaN, devuelve falso.
- Si y es NaN, devuelve falso.
- Si x es el mismo valor numérico que y, devuelve verdadero.
- Si x es +0 e y es −0, devuelve verdadero.
- Si x es −0 e y es +0, devuelve verdadero.
- Falso retorno.
(...)
(Lo mismo ocurre por +0 == -0
cierto.)
Parece lógico tratar +0
a y -0
como iguales. De lo contrario, tendríamos que tener esto en cuenta en nuestro código y yo, personalmente, no quiero hacer eso;)
Nota:
ES2015 introduce un nuevo método de comparación Object.is
. Object.is
distingue explícitamente entre -0
y +0
:
Object.is(-0, +0); // false
Agregaré esto como respuesta porque pasé por alto el comentario de @ usuario113716.
Puedes probar -0 haciendo esto:
function isMinusZero(value) {
return 1/value === -Infinity;
}
isMinusZero(0); // false
isMinusZero(-0); // true
Acabo de encontrar un ejemplo en el que +0 y -0 se comportan de manera muy diferente:
Math.atan2(0, 0); //returns 0
Math.atan2(0, -0); //returns Pi
Tenga cuidado: incluso cuando use Math.round en un número negativo como -0.0001, en realidad será -0 y puede arruinar algunos cálculos posteriores como se muestra arriba.
Una forma rápida y sucia de solucionar este problema es hacer algo como:
if (x==0) x=0;
o solo:
x+=0;
Esto convierte el número a +0 en caso de que fuera -0.
la respuesta de 2021
¿Son +0 y -0 lo mismo?
Respuesta corta: dependiendo del operador de comparación que utilice.
Respuesta larga:
Básicamente, hasta ahora hemos tenido 4 tipos de comparación :
- igualdad 'laxa'
console.log(+0 == -0); // true
- igualdad 'estricta'
console.log(+0 === -0); // true
- Igualdad de 'mismo valor' ( ES2015
Object.is
)
console.log(Object.is(+0, -0)); // false
- Igualdad de 'mismo valor-cero' ( ES2016 )
console.log([+0].includes(-0)); // true
Como resultado, apenas Object.is(+0, -0)
marca la diferencia con los demás.
const x = +0, y = -0; // true -> using ‘loose’ equality
console.log(x === y); // true -> using ‘strict’ equality
console.log([x].indexOf(y)); // 0 (true) -> using ‘strict’ equality
console.log(Object.is(x, y)); // false -> using ‘Same-value’ equality
console.log([x].includes(y)); // true -> using ‘Same-value-zero’ equality