¿Qué hace ~~ ("doble tilde") en Javascript?
Hoy estaba revisando una biblioteca de física de juegos en línea y me encontré con el operador ~~. Sé que un solo ~ es un NOT bit a bit, eso convertiría a ~~ en un NOT de un NOT, lo que devolvería el mismo valor, ¿no?
Elimina todo lo que está después del punto decimal porque los operadores bit a bit convierten implícitamente sus operandos en enteros de 32 bits con signo. Esto funciona ya sea que los operandos sean números (de punto flotante) o cadenas, y el resultado sea un número.
En otras palabras, se obtiene:
function(x) {
if(x < 0) return Math.ceil(x);
else return Math.floor(x);
}
sólo si x está entre -(2 31 ) y 2 31 - 1. De lo contrario, se producirá un desbordamiento y el número "volverá".
Esto puede considerarse útil para convertir el argumento de cadena de una función en un número, pero debido a la posibilidad de desbordamiento y a que es incorrecto usarlo con números no enteros, no lo usaría de esa manera excepto para "código golf" (es decir recortar inútilmente bytes del código fuente de su programa a expensas de la legibilidad y la robustez). Yo usaría +x
o Number(x)
en su lugar.
Cómo este es el NO del NO
El número -43,2, por ejemplo es:
-43,2 10 = 11111111111111111111111111010101 2
como un número binario de 32 bits con signo (complemento a dos). (JavaScript ignora lo que hay después del punto decimal). Al invertir los bits se obtiene:
NO -43 10 = 000000000000000000000000000101010 2 = 42 10
Invertir nuevamente da:
NO 42 10 = 11111111111111111111111111010101 2 = -43 10
Esto se diferencia Math.floor(-43.2)
en que los números negativos se redondean hacia cero, no hacia afuera. (La función piso, que sería igual a -44, siempre se redondea hacia abajo al siguiente entero inferior, independientemente de si el número es positivo o negativo).
El primer operador ~ fuerza el operando a un número entero (posiblemente después de convertir el valor a una cadena o un booleano), luego invierte los 31 bits más bajos. Oficialmente, los números de ECMAScript son todos de punto flotante, pero algunos números se implementan como enteros de 31 bits en el motor SpiderMonkey.
Puedes usarlo para convertir una matriz de 1 elemento en un número entero. Los puntos flotantes se convierten según la regla C, es decir. truncamiento de la parte fraccionaria.
El segundo operador ~ luego invierte los bits nuevamente, para que sepas que tendrás un número entero. Esto no es lo mismo que forzar un valor a booleano en una declaración de condición, porque un objeto vacío {} se evalúa como verdadero, mientras que ~~{} se evalúa como falso.
js>~~"yes"
0
js>~~3
3
js>~~"yes"
0
js>~~false
0
js>~~""
0
js>~~true
1
js>~~"3"
3
js>~~{}
0
js>~~{a:2}
0
js>~~[2]
2
js>~~[2,3]
0
js>~~{toString: function() {return 4}}
4
js>~~NaN
0
js>~~[4.5]
4
js>~~5.6
5
js>~~-5.6
-5
En ECMAScript 6, el equivalente a ~~
es Math.trunc :
Devuelve la parte integral de un número eliminando los dígitos fraccionarios. No redondea ningún número.
Math.trunc(13.37) // 13
Math.trunc(42.84) // 42
Math.trunc(0.123) // 0
Math.trunc(-0.123) // -0
Math.trunc("-1.123")// -1
Math.trunc(NaN) // NaN
Math.trunc("foo") // NaN
Math.trunc() // NaN
El polirelleno:
function trunc(x) {
return x < 0 ? Math.ceil(x) : Math.floor(x);
}