Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Javascript's Math.floor the slowest way to calculate floor in Javascript?

I'm generally not a fan of microbenchmarks. But this one has a very interesting result.
http://ernestdelgado.com/archive/benchmark-on-the-floor/

It suggests that Math.floor is the SLOWEST way to calculate floor in Javascript. ~~n, n|n, n&n all being faster.
This seems pretty shocking as I would expect that people implementing Javascript in today's modern browsers would be some pretty smart people.

Does floor do something important that the other methods fail to do? Is there any reason to use it?

like image 853
Mark Bolusmjak Avatar asked Mar 26 '10 20:03

Mark Bolusmjak


People also ask

What does Math floor () do in JavaScript?

floor() The Math. floor() function returns the largest integer less than or equal to a given number.

What is the difference between Math Trunc () and Math floor () in JavaScript?

Math. trunc rounds down a number to an integer towards 0 while Math. floor rounds down a number to an integer towards -Infinity . As illustrated with the following number line, the direction will be the same for a positive number while for a negative number, the directions will be the opposite.

What is the difference between Math floor and Math round?

Math. round() - rounds to the nearest integer (if the fraction is 0.5 or greater - rounds up) Math. floor() - rounds down.

What does the floor () method do?

Floor() is a Math class method. This method is used to find the largest integer, which is less than or equal to the passed argument.


1 Answers

The primary reason Math.floor is slower (where it actually is--in some tests I've done it's faster) is that it involves a function call. Older JavaScript implementations couldn't inline function calls. Newer engines can inline the call, or at least make the property lookup faster, but they still need a guard condition in case you (or some other script) overwrote the Math.floor function. The overhead is minimal though, so there's not much difference in speed.

More importantly though, as was mentioned in several comments, the other methods are not equivalent. They all work by doing bitwise operations. The bitwise operators automatically convert their operands to 32-bit integers by truncating the number. That's fine if the number fits in 32 bits, but JavaScript numbers are 64-bit floats, which could be much larger than 2147483647.

They also give a different result for negative numbers, since converting to integers truncates and Math.floor always rounds down. For example, Math.floor(-2.1) === -3, but (-2.1) | (-2.1) === -2.

If you know you are only dealing with positive numbers less than 2147483648, and you need to squeeze every bit of performance out of your code in older browsers (Make sure it's actually the bottleneck first. It probably isn't.), I would use an even simpler method: x|0. It doesn't evaluate the variable twice, and it works even if x is an expression (just be sure to put it in parentheses so you don't run into precedence issues).

like image 86
Matthew Crumley Avatar answered Oct 13 '22 21:10

Matthew Crumley