2011-01-06 17 views
5

Estoy usando Math.ceil(Math.abs(x)) dentro de un bucle.Javascript Math.ceil (Math.abs()) optimización

¿Alguien puede realizar alguna optimización para esta operación? (Bit a bit o qué?)

Usted es agradable de referencia en jsperf.com

+0

PS: Necesito el valor de retorno de la operación, no la condición es < or > algo – Dan

+0

Me temo que no es más sencillo de lo que lo has hecho. –

+1

He cambiado el valor de la prueba a un valor flotante negativo en lugar de un número entero, por lo que el código realmente tiene que hacer algo. – OrangeDog

Respuesta

8

Math.abs no recibe más simple de acuerdo con webkit JavaScriptCore

case MathObjectImp::Abs: 
result = (arg < 0 || arg == -0) ? (-arg) : arg; 

Sin embargo ceil utiliza la función ceil de C

case MathObjectImp::Ceil: 
    result = ::ceil(arg); 

lo que las pruebas en JSpref http://jsperf.com/math-ceil-vs-bitwise a nivel de bits es más rápido
prueba de @ orangedog respuesta http://jsperf.com/math-ceil-vs-bitwise/2 Math.ceil es más rápido

así que supongo que su mejor opción es:

var n = Math.abs(x); 
var f = (n << 0), 
f = f == n ? f : f + 1; 
+0

¡Bien hecho, has hecho una gran investigación en la fuente de Webkit! – Dan

2

Javascript no es un lenguaje compilado como C, operaciones bit a bit por lo que puede hacer maravillas en estos idiomas, no son tan grandes en JS porque los números se almacenan como puntos flotantes de 64 bits. Eche un vistazo a este SO post.

Incluso entonces, lo que escriba en JS se transformará en código nativo de alguna manera por el navegador subyacente y podría ser más rápido o más lento, dependiendo de la implementación.

Dado que Math.ceil y Math.abs están incorporados; Supongo que están muy optimizados, así que dudo que puedas obtener un mejor rendimiento haciendo algunos trucos propios.

En pocas palabras: tres cosas se interponen en su camino de hacerlo más rápido:

  1. representación de números en JS
  2. hecho de que es un lenguaje interpretado
  3. funciones que utiliza son "nativo", por lo que debe ser lo suficientemente rápido en su propia
+1

te estás olvidando de sobrecarga de despacho - usar operadores en lugar de métodos acelerará el código – Christoph

+1

Aunque aparentemente en los números JS todos son dobles, todos los motores JS realmente almacenan valores en enteros cuando sea posible, por lo que los operadores bit a bit siguen siendo rápidos ya que no se necesita conversión cuando el número ya es un número entero. – gsnedders

1

parseInt(Math.abs(x)) + 1 es más rápido en un 30% en Firefox acuerdo con jsperf

Como el argumento siempre es positivo, las ramas en Math.ceil() son innecesarias.

+3

Puede o no ser más rápido, pero también es incorrecto: cualquier número con un componente fraccional de valor cero será incorrectamente 1 mayor que el valor límite. – annakata

+0

Ah, buen punto. La comprobación de esto, como era de esperar, lo hace más lento de nuevo. – OrangeDog

1

Aquí hay otro, que no necesita hacer ninguna de búsqueda:

((x >= 0 ? x : -x) + 0.5) >> 0 
+1

http://jsperf.com/best-math-ceil-math-abs/2 ganador! – Dan

+0

El redondeo aquí es 'Math.round' no' Math.ceil'. – MikeM

2

x < 0 ? Math.ceil(-x) : Math.ceil(x) produce un aumento de velocidad del 40% en Firefox 3.6 (poca diferencia en los demás) mientras permanecen relativamente legibles.

Aquí está el jsPerf page. Ignore la etiqueta "algunos operadores bit a bit"; la expresión de arriba no usa ninguna.

+0

Misma velocidad en Chrome –

+1

I [encontrado con jsperf] (http://jsperf.com/two-max-bound-functions) que hacer algo de bit a bit es más rápido que una función de techo en este caso. – starwed

-1

Dos maneras más rápidas de hacer cálculos (que dan casi la misma velocidad en los navegadores modernos):

function f (n) { 
    return (~~n) + 1; 
} 

// or 

function f1 (n) { 
    return (n | 0) + 1; 
} 

// some tests, ~~ operator seems to work identicaly on numbers: 

(3.3 | 0) === 3; 
(3.8 | 0) === 3; 
(-3.3 | 0) === -3; 
(-3.8 | 0) === -3; 

a diferencia Math.floor(-3.3) == Math.floor(-3.8) == -4

+0

'f1 (1); // 2.' Estas funciones no siguen el comportamiento 'Math.ceil'. Tal vez deberías aceptar la respuesta mejor calificada, en lugar de la tuya. – MikeM