lunes, 22 de julio de 2013

Doble negación binaria (~~) para redondear en JavaScript

Alguna vez te puedes encontrar en JavaScript con una línea como esta:

var mins = ~~(seconds / 60);

¿Que significa el doble símbolo "~~"?¿que hace?

El operador ~

~ es un operador binario de negación o complemento (bitwise NOT operator). Este operador convierte el operando en un entero de 32 bits para luego invertir cada bit individualmente. Los ceros se convierten en unos y los unos en ceros.

El operador doble (~~) se utiliza para redondear, como un equivalente rápido de Math.floor(). Al invertir los bits dos veces quedan igual que antes, pero la conversión a entero permanece (utiliza el método interno ToInt32).

~~5.7;       // => 5 
~~32.18897;  // => 32
~~5.7e1;     // => 57  (podemos utilizar notación exponencial)
~~314e-2;    // => 3

Lo que hace realmente la doble negación binaria es eliminar cualquier número despues de la coma (truncar, más que redondear). Para los número positivos esto es equivalente a Math.floor(), pero para los números negativos no. Para los negativos es equivalente a Math.ceil(), ya que redondea hacia cero:

~~-5.7;                // => -5
Math.floor(-5.7)       // => -6 
Math.ceil(-5.7)        // => -5
~~-32.18897;           // => -32
Math.floor(-32.18897)  // => -33
Math.ceil(-32.18897)   // => -32

Mas diferencias con Math.floor()

Ademas de que el redondeo de números negativos no es igual, si el operando no es convertible a número, no nos va a devolver NAN, sino 0.

~~"abc";     // => 0 
~~null;      // => 0
~~undefined; // => 0
~~{};        // => 0
~~[];        // => 0
~~(1/0);     // => 0
~~false;     // => 0
~~true;      // => 1 //true es convertible a 1

La ganancia de rendimiento con los nuevos motores de JavaScript es mínima y la pérdida de legibilidad del código es importante. Mas que un atajo es un antipatrón, es decir, una mala forma de solucionar un problema.

Fuentes:
Double bitwise NOT (~~)
Tilde or the Floor? Practical use for JavaScript bitwise operators
Stackoverflow: What is the “double tilde” (~~) operator in JavaScript?

No hay comentarios:

Publicar un comentario