tags:

views:

1283

answers:

5

pretty straightforward but i just want to know which is faster... coz i believe simply multiplying a number by -1 is much faster than calling a predefined method, provided that you are sure that value is negative.. but if that's the case then what is the abs() function for? -simply for making sure that the value returned would always be positive regardless of value's sign??

+10  A: 

I suppose it depends on the implementation, but Math.abs could be as simple as:

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

So, in theory, it just adds a quick test before multiplying.

But, yes, negating a negative sign is the sole purpose. The point is that a simple x * -1 is also counter-productive for positive values.


@olliej [comments]

True. Simple edit, though. ;)

function abs(x) {
    return Number(x < 0 ? x * -1 : x);
}
Jonathan Lonowski
That's not *technically* correct as abs is defined as return a number. If i did abs(true) or abs(false) i should get 0 or 1, whereas your function will produce true or false.function abs(x) { if (x < 0) return -x; return +x; }should do, but i'm not 100% it will handle 0/-0 correctly.
olliej
(Random factoid: in current WebKit nightlies that's actually faster than using Math.abs)
olliej
You don't want the call to Number, that requires a resolve to the global object, etc. Unary + does sufficient work.
olliej
Instead of doing your own abs you can use the browsers built in: var abs = Math.abs; alert( abs(-1) );
some
+11  A: 

I would suggest picking the method that more clearly shows your intention, rather than worrying about the performance. In this case, the performance gain of multiplying by -1 is probably minimal.

When you use Math.abs(), it is very clear that you want a positive value. When you use * -1 it is not clear, and requires more investigation to determine if the input value is always negative.

Brannon
+16  A: 

I did some profiling with these implementations:

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

I got the following result on my Win XP with Crome 1.0.154.36, Opera 9.61, Firefox 3.0.5 and IE 7.0.5730.11 (values are normalized after the fastest result):

         Test 1    Test 2    Test 3
Browser  abs(a)      a*-1        -a
Crome       1.7       1.1       1.0
Opera       8.3       4.5       4.0
FF         10.5       7.7       7.2
IE         25.6      10.8       9.4

Conclusion: -a is the fastest, tightly followed by a*-1. abs(a) is the slowest but most clear way to do it.

My Recommendation: Use Math.abs(a). If you are in a tight loop and by profiling has found it to be too slow, you can use a local reference to the abs function:

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;

If I had added the local reference to the table above it would have been 1.3 for Crome, 6.1 for Opera, 7.2 for Firefox and 19.7 for IE.

If it still is to slow and your profiling shows it is because of the abs(a) you can change calls to abs(a) with inline test3. However, on my 1.7GHz machine IE only took 890ms to do 500 000 test of Math.abs(a).

some
A: 

Just the *-1 operation is probably faster, but keep in mind that the end result differs from the result for math.abs().

math.abs(-5) and math.abs(5) both return 5.

-5 * -1 returns 5 as well.

5 * -1 returns -5.

So unless you're absolutely sure that the number is negative to begin with, you have to do some tests, which cost more time. Might as well do math.abs().

But really, if the performance difference between abs() and *-1 matters in your JS, your probably have more serious issues.

Sietse
+1  A: 

A style question: Why use a * -1 instead of -a? Apart from that I agree that you should use abs() if you don't know the sign of the number beforehand. I would not care for speed but for readability.

unbeknown
I wonder that too.
some