2009-01-14 21 views
32

Bastante sencillo, pero solo quiero saber cuál es más rápido.¿Qué es más rápido: Math.abs (value) o value * -1?

Creo que simplemente multiplicar un número por -1 es mucho más rápido que llamar a un método predefinido, siempre que esté seguro de que el valor es negativo.

Pero si ese es el caso, entonces ¿para qué sirve la función abs()? ¿Es simplemente para asegurarse de que el valor devuelto siempre sea positivo independientemente del signo del valor?

+5

De hecho, puede ser más rápido usar -x en lugar de x * -1. – Prestaul

+2

Respuesta rápida para la gente del futuro: [tampoco, realmente.] (Http://jsperf.com/abs-vs-n1) – Tortoise

+1

.. a menos que use una función personalizada: http://jsperf.com/math -abs-vs-custom-abs-function donde 'Math.abs()' gana masivamente que cualquier otra cosa. – h2ooooooo

Respuesta

65

Actualización de agosto de 2012:

he hecho un poco de perfiles con estas implementaciones:

/* Test 1: */ b = Math.abs(a); 
/* Test 2: */ b = abs(a); //local copy: abs = Math.abs; 
/* Test 3: */ b = a < 0 ? a * -1 : a; 
/* Test 4: */ b = a < 0 ? -a : a; 

me dieron el siguiente resultado en Windows 7. Los valores se normalizan tras el resultado más rápido por el navegador para que sea más fácil comparar qué método es más rápido:

 1:Math 2:abs 3:*-1 4:- 1.0= Version 
Chrome 1.0 1.0 1.0 1.0 111ms 21.0.1180.75 m 
Firefox 1.0 1.0 1.2 1.2 127ms 14.0.1 
IE  1.4 1.0 1.1 1.0 185ms 9.0.8112 
Opera  1.9 1.6 1.1 1.0 246ms 12.00 
Safari 1.6 1.6 1.1 1.0 308ms 5.1.7 

Conclusión: Cuando hice esta prueba hace 3 años, -a fue más rápido, pero ahora Math.abs (x) es más rápido en Firefox. En Chrome abs(a) y -a obtuve el mismo tiempo y solo hubo 3 ms de diferencia con el método más lento cuando lo probé con 10 000 000 de números.

Mi recomendación: Utilice Math.abs (a). Si se encuentra en un bucle estrecho y por un perfil ha encontrado que es demasiado lento, puede utilizar una referencia local a la función ABS:

var abs=Math.abs; //A local reference to the global Math.abs function 
for (i=0;i<1234567890;++i) if (abs(v[i]) > 10) ++x; 
10

supongo que depende de la implementación, pero Math.abs podría ser tan simple como:

function abs(x) { 
    return x < 0 ? x * -1 : x; 
} 

Por lo tanto, en teoría, que sólo añade una prueba rápida antes de multiplicar.

Pero, sí, negar un signo negativo es el único propósito. El punto es que un simple x * -1 también es contraproducente para valores positivos.


@olliej [comentarios]

verdadera. Edición simple, sin embargo. ;)

function abs(x) { 
    return Number(x < 0 ? x * -1 : x); 
} 
+1

No es * técnicamente * correcto ya que abs se define como devolver un número. Si hiciera abs (verdadero) o abs (falso) debería obtener 0 o 1, mientras que su función producirá verdadero o falso. función abs (x) {if (x <0) return -x; return + x; } debería hacer, pero no soy 100% manejará 0/-0 correctamente. – olliej

+0

(Factoid aleatorio: en los fotolitos de WebKit actuales que es realmente más rápido que usar Math.abs) – olliej

+0

No desea la llamada a Number, que requiere una resolución para el objeto global, etc. Unary + hace suficiente trabajo. – olliej

22

Yo sugeriría escoger el método que muestra más claramente su intención, en lugar de preocuparse por el rendimiento. En este caso, la ganancia de rendimiento de multiplicar por -1 es probablemente mínima.

Cuando usa Math.abs(), está muy claro que desea un valor positivo. Cuando usa * -1 no está claro, y requiere más investigación para determinar si el valor de entrada es siempre negativo.

+6

+1. La primera regla de optimización: * "no lo hagas" *. La segunda regla de optimización (¡sólo expertos!): * "No lo hagas ... todavía." * :-) – HostileFork

+0

Inicialmente quise estar en desacuerdo con tu respuesta by-the-book para evitar optimizaciones prematuras, como JS * * estaba ** faltando optimizaciones del compilador debido a ** interpretación **. Tenía sentido usar estos pequeños trucos para aumentar el rendimiento, si realmente importaba. Sin embargo, los navegadores modernos ** do (jit-) compilan ** JS, haciendo tales optimizaciones cada vez más obsoletas. – mucaho

3

Sólo la operación *-1 es probablemente más rápido, pero tenga en cuenta que la resultado final difiere del resultado de math.abs().

math.abs(-5) y math.abs(5) ambos devuelven 5.

-5 * -1 retornos 5 también.

5 * -1 devuelve -5.

Así que, a menos que esté absolutamente seguro de que el número es negativo para empezar, tiene que hacer algunas pruebas, que cuestan más tiempo. También podría hacer math.abs().

Pero en realidad, si la diferencia de rendimiento entre abs() y * -1 importa en su JS, es probable que tenga problemas más serios.

1

Una pregunta de estilo: ¿Por qué usar a * -1 en lugar de -a? Además de eso, acepto que debe usar abs() si no conoce el signo del número de antemano. No me importaría la velocidad, sino la legibilidad.

+0

Me pregunto eso también. – some

Cuestiones relacionadas