Javascript: Math.floor(var) versus var | 0

So I was looking at a javascript and I saw someone using the bitwise or ( ‘|’ ) in a function. I had never seen this so I tested it out using the console.

console.warn (5 | 0); <— returns 5
console.warn (5.1 | 0); <— returns 5
console.warn (5.9 | 0); <— returns 5

Is doing a bitwise or on a number cheaper than calling the Math.floor function? Is it doing something else that I’m not seeing?

Here’s the script I found it in:



function shuffle (inArray){
   var slotToSwap = inArray.Length, temp, newSlot;
   while (slotToSwap-- ){
      **newSlot = (Math.random() * slotToSwap) | 0;**
      temp = inArray[slotToSwap];
      inArray[slotToSwap] = inArray[newSlot];
      inArray[newSlot] = temp;
   }
   return inArray;
}


Hint: what happens if you try



console.warn( 43674343743.87373 | 0 )


console.warn (Math.floor (43674343743.87373)) <— 43674343743
console.warn (43674343743.87373 | 0) <-- 724670783

It looks like for really large arrays, the above function would fail. So to be safe it really is better to use the Math.floor.

On a hunch, I guessed it was breaking on 2^32, but I was wrong. 2^32 returns a negative number.

Your suspicion is right. Bitwise operators in JavaScript only work on signed 32-bit ints. Since JS doesn’t really have integers, the argument is silently converted to one internally before the operation is applied. That truncates the decimal portion, and for any float that holds a really big number, you’ll get a weird result.

Also note that truncation is a different operation than floor.



console.warn( -42.9 | 0 )
console.warn( Math.floor( -42.9 )


Gotcha, thank you.

Never mind!

It’s safer to use Math.floor, it produces far more intelligible code, it gives the reader a better understanding of the intent of the code, and optimizing javascript code by avoiding a call to Math.floor is like ordering a Diet Coke with your ice cream sundae.

Even if it always worked, it’d still be a bad idea. It’s reaching down into a lower level of abstraction. The whole point of a programming language is that you shouldn’t have to do that-- What happens when someone writes a new implementation that interacts with that lower level in a different way?

And even if that doesn’t happen, either, it makes the code harder to understand for no good reason: Even if it really were the most efficient way to do it, it’s not your responsibility to recognize that-- It’s the responsibility of whoever wrote the floor() function. Trust that he was doing his job right, and just use the tool designed for the purpose.

Okay, for fun here’s the completed version. I made it a prototype function just because that’s what I was trying to teach myself at the time. Thanks for all your input :slight_smile:


// Create a function to shuffle the elements of an array
if (!Array.prototype.shuffle){
   Array.prototype.shuffle = function (){
      var eltToSwap = this.length, temp, idx;
      while (eltToSwap--){
      idx = Math.floor((Math.random() * eltToSwap));
         temp = this[eltToSwap];
         this[eltToSwap] = this[idx];
         this[idx] = temp;
      }
   };
}

and a test web page that scrambles the words every second:


<!DOCTYPE html>
<html>
  <head>
   <base href="file:///c:/xxxxxx/program/web/" target="_blank" />
   <meta name="description" content="Test Javascript" />
   <script src="JavaScriptLibrary.js"></script>
   <script>
      var a = ["This", "Is", "A", "Test"];
   </script>
  </head>

  <body>
   <div id="main">
     <div id="title">WEB PAGE</div>
      <p><hr width="50%" align="left" />This is a Sentence</p>

      <!-- This below paragraph should not be displayed -->
      <p hidden="hidden">This paragraph is hidden</p>
    </div>

    <script>
       var randomWords = setInterval (function (){
           var d=document.getElementById("title");
	   a.shuffle();
	   d.innerHTML=a;
	}, 1000);
    </script>

  </body>
</html>

Abstractions are ideally supposed to interface with lower-level abstractions in specific well-defined ways such that the lower-level abstraction never shows through. In practice, this seems difficult to do, in which case the upper-level abstraction is called leaky.

Joel Spolsky has an essay on the subject: The Law of Leaky Abstractions (November 2002) in which he argues that all non-trivial abstractions are leaky, and gives various examples.

His basic thesis is that abstractions never seem to quite simplify the programmer’s life as much as they were meant to, because there are always problems with them that the program has to allow for and program around (involving implementation details and problems with lower-level abstractions), which are the very things the programmer was supposed to not even have to know about.

Negative numbers would also produce different results.

Sometimes you need performance at all costs, though. Knuth was correct in that “premature optimization is the root of all evil”, but he didn’t use the word “premature” for no reason.

The first question here is if it’s actually faster. I used jsperf.com to do a quick comparison, and it appears that there is some benefit–about 20% as reported, though a bit higher in reality since there’s a certain amount of loop overhead.

A while back I was writing some Javascript to do some heavy-duty signal processing. It’s about the worst possible language for this task, but it’s the only language that you can run on any device (from cell phone to desktop) with no installation required. I used several tricks but it was still too slow for portable devices. Having a few more tricks up my sleeve might have made it practical.

If it really is more efficient and the existing floor() function wasn’t written that way to begin with, then the proper course of action would be for you to be the guy who wrote the floor() function. That is, you’d write a new function that uses the trick, and then call that function whenever you need to use it, and hope that the compiler you’re using unfolds the necessary overhead out of the function call.

For a real-world example where all of this really is relevant: One operation often encountered in 3D graphics is the inverse square root: That is, given x, find 1/sqrt(x). Now, the naive way of doing this is fairly slow, but computer games absolutely must be fast. So it was worthwhile to find a quicker way to do it, at all costs, and in the early 90s, someone (precisely who is lost to history) figured out a really clever but mostly incomprehensible trick to do it.

But that person (whoever it was) didn’t just use that trick directly in the code everywhere it was needed. Instead, he wrote a function called Q_rsqrt(), and hid all of the ugliness inside that function. A person reading most of the code, then, would just say “Oh, that’s the inverse square root function”, and not worry about how it works. Only if someone actually delved in to the function itself would they have to worry about the details, and if they did so, they would discover that even the original programmer thought it bizarre, with comments like “// evil floating point bit level hacking” and “// what the fuck?”.

It’s important to note, by the way, that “shuffle off the work to that poor sap writing the function” is a good idea even if you yourself are that poor sap. Even if you can think of all of the details, you can’t think of them all at once. Hiding them away in separate functions allows you to think about things only when necessary.

I would agree, except that Javascript (on Chrome, IE, and Firefox) does not in fact fully compile away its high function call overhead, as you can see from this comparison (oddly, Firefox seems to “semi-inline” the function, because Math.floor is actually faster than the local function).

Languages which are are perf oriented tend to have features that allow better expression of these kinds of hacks, such as a preprocessor, function inlining, and templates. Javascript has none of that, unfortunately. Ideally, one would choose a language better suited to the task, but there isn’t one (at least not until Google’s NaCl improves!).

Hacks like this are definitely the last thing you should do, but that doesn’t mean they should never be done. Just… very sparingly. Algorithmic improvements come first, as always.

There’s something you’re not seeing, because this isn’t the correct question.

The correct question is “is converting to integer and doing a bitwise OR faster than floor?”

Folks above covered quite well the issue of whether it’s better, regardless of whether it’s faster. The general rule is “do what’s better unless it has to be faster”. For the vast majority of programming projects, only a small portion needs to be optimized. That is, most optimizations won’t provide a meaningful return on investment; only the code that is in the tightest loops needs to be optimized. There are lots of caveats, of course.

Sidestepping that, though, the question remains, which is faster? You’d have to test to find out. My suspicion is that they’d be pretty close.

Finally, I’m not a javascript guru, but if the language doesn’t have integers, then my guess is I didn’t quite get the question right, above. If so, it would be:

Which is faster: floor, or converting to integer, doing bitwise OR, and then converting back to float?

There may be cases when the javascript interpreter can avoid the latter conversion, though.

My guess is that floor is about the same cost as converting to integer, but I’ve never implemented it so I can’t say.