Javascript representa Number
como números flotantes de doble precisión de 64 bits .
Math.floor
trabaja con esto en mente.
Las operaciones bit a bit funcionan en enteros con signo de 32 bits . Los enteros con signo de 32 bits usan el primer bit como significante negativo y los otros 31 bits son el número. Debido a esto, los números mínimos y máximos permitidos de 32 bits con signo son -2,147,483,648 y 2147483647 (0x7FFFFFFFF), respectivamente.
Entonces, cuando lo estás haciendo | 0
, esencialmente lo estás haciendo & 0xFFFFFFFF
. Esto significa que cualquier número que se represente como 0x80000000 (2147483648) o mayor regresará como un número negativo.
Por ejemplo:
// Safe
(2147483647.5918 & 0xFFFFFFFF) === 2147483647
(2147483647 & 0xFFFFFFFF) === 2147483647
(200.59082098 & 0xFFFFFFFF) === 200
(0X7FFFFFFF & 0xFFFFFFFF) === 0X7FFFFFFF
// Unsafe
(2147483648 & 0xFFFFFFFF) === -2147483648
(-2147483649 & 0xFFFFFFFF) === 2147483647
(0x80000000 & 0xFFFFFFFF) === -2147483648
(3000000000.5 & 0xFFFFFFFF) === -1294967296
También. Las operaciones bit a bit no se "plantan". Se truncan , lo que es lo mismo que decir, redondean más cerca 0
. Una vez que pasan en torno a los números negativos, Math.floor
rondas abajo , mientras que a nivel de bits comienzan redondeo hacia arriba .
Como dije antes, Math.floor
es más seguro porque funciona con números flotantes de 64 bits. Bitwise es más rápido , sí, pero está limitado al alcance firmado de 32 bits.
Para resumir:
- Bitwise funciona igual si trabajas desde
0 to 2147483647
.
- Bitwise tiene 1 número de descuento si trabaja desde
-2147483647 to 0
.
- Bitwise es completamente diferente para números menores
-2147483648
y mayores que 2147483647
.
Si realmente quieres modificar el rendimiento y usar ambos:
function floor(n) {
if (n >= 0 && n < 0x80000000) {
return n & 0xFFFFFFFF;
}
if (n > -0x80000000 && n < 0) {
return (n - 1) & 0xFFFFFFFF;
}
return Math.floor(n);
}
Solo para agregar Math.trunc
trabajos como operaciones bit a bit. Entonces puedes hacer esto:
function trunc(n) {
if (n > -0x80000000 && n < 0x80000000) {
return n & 0xFFFFFFFF;
}
return Math.trunc(n);
}