Javascript representa Number
como números flutuantes de precisão dupla de 64 bits .
Math.floor
trabalha com isso em mente.
As operações bit a bit funcionam em números inteiros assinados de 32 bits . Inteiros com sinal de 32 bits usam o primeiro bit como significante negativo e os outros 31 bits são o número. Por esse motivo, os números mínimo e máximo permitidos para números assinados de 32 bits são -2.147.483.648 e 2147483647 (0x7FFFFFFFF), respectivamente.
Então, quando você está fazendo | 0
, você está essencialmente fazendo é& 0xFFFFFFFF
. Isso significa que qualquer número representado como 0x80000000 (2147483648) ou superior retornará como um número negativo.
Por exemplo:
// 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
Além disso. As operações bit a bit não "atendem". Eles truncam , o que é o mesmo que dizer, eles se aproximam mais 0
. Depois de ir ao redor para números negativos, Math.floor
rodadas para baixo , enquanto start bit a bit arredondamento para cima .
Como eu disse antes, Math.floor
é mais seguro porque opera com números flutuantes de 64 bits. Bitwise é mais rápido , sim, mas limitado ao escopo assinado de 32 bits.
Para resumir:
- Bitwise funciona da mesma forma se você trabalhar
0 to 2147483647
.
- Bitwise é um número desativado se você trabalha
-2147483647 to 0
.
- Bitwise é completamente diferente para números menores que
-2147483648
e maiores que 2147483647
.
Se você realmente deseja ajustar o desempenho e usar os dois:
function floor(n) {
if (n >= 0 && n < 0x80000000) {
return n & 0xFFFFFFFF;
}
if (n > -0x80000000 && n < 0) {
return (n - 1) & 0xFFFFFFFF;
}
return Math.floor(n);
}
Apenas para adicionar Math.trunc
trabalhos como operações bit a bit. Então você pode fazer isso:
function trunc(n) {
if (n > -0x80000000 && n < 0x80000000) {
return n & 0xFFFFFFFF;
}
return Math.trunc(n);
}