Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using bitwise OR 0 to floor a number

People also ask

How do you make Bitwise and zero?

First, Let's say some rules: 1) If two numbers are equal, no numbers will be between them. 2) If Two numbers are not Equal, The consecutive number between them Will contain ZERO at each digit, thus their bitwise AND will be ZERO.

What is the result of the Bitwise operation 1 & 0?

The result of the bitwise AND operation is 1 if both the bits have the value as 1; otherwise, the result is always 0.

How do you negate a number using bitwise operations?

The ~ (bitwise negation) operator yields the bitwise complement of the operand. In the binary representation of the result, every bit has the opposite value of the same bit in the binary representation of the operand.

What is Bitwise not of 1?

Overview# Bitwise NOT (or complement) is a Bitwise operation, is a unary operation that performs logical negation on each bit, forming the ones' complement of the given binary value. Bits that are 0 become 1, and those that are 1 become 0.


How does it work? Our theory was that using such an operator casts the number to an integer, thus removing the fractional part

All bitwise operations except unsigned right shift, >>>, work on signed 32-bit integers. So using bitwise operations will convert a float to an integer.

Does it have any advantages over doing Math.floor? Maybe it's a bit faster? (pun not intended)

http://jsperf.com/or-vs-floor/2 seems slightly faster

Does it have any disadvantages? Maybe it doesn't work in some cases? Clarity is an obvious one, since we had to figure it out, and well, I'm writting this question.

  • Will not pass jsLint.
  • 32-bit signed integers only
  • Odd Comparative behavior: Math.floor(NaN) === NaN, while (NaN | 0) === 0

This is truncation as opposed to flooring. Howard's answer is sort of correct; But I would add that Math.floor does exactly what it is supposed to with respect to negative numbers. Mathematically, that is what a floor is.

In the case you described above, the programmer was more interested in truncation or chopping the decimal completely off. Although, the syntax they used sort of obscures the fact that they are converting the float to an int.


In ECMAScript 6, the equivalent of |0 is Math.trunc, kind of I should say:

Returns the integral part of a number by removing any fractional digits. It just truncate the dot and the digits behind it, no matter whether the argument is a positive number or a negative number.

Math.trunc(13.37)   // 13
Math.trunc(42.84)   // 42
Math.trunc(0.123)   //  0
Math.trunc(-0.123)  // -0
Math.trunc("-1.123")// -1
Math.trunc(NaN)     // NaN
Math.trunc("foo")   // NaN
Math.trunc()        // NaN

Your first point is correct. The number is cast to an integer and thus any decimal digits are removed. Please note, that Math.floor rounds to the next integer towards minus infinity and thus gives a different result when applied to negative numbers.


Javascript represents Number as Double Precision 64-bit Floating numbers.

Math.floor works with this in mind.

Bitwise operations work in 32bit signed integers. 32bit signed integers use first bit as negative signifier and the other 31 bits are the number. Because of this, the min and max number allowed 32bit signed numbers are -2,147,483,648 and 2147483647 (0x7FFFFFFFF), respectively.

So when you're doing | 0, you're essentially doing is & 0xFFFFFFFF. This means, any number that is represented as 0x80000000 (2147483648) or greater will return as a negative number.

For example:

 // Safe
 (2147483647.5918 & 0xFFFFFFFF) ===  2147483647
 (2147483647      & 0xFFFFFFFF) ===  2147483647
 (200.59082098    & 0xFFFFFFFF) ===  200
 (0X7FFFFFFF      & 0xFFFFFFFF) ===  0X7FFFFFFF

 // Unsafe
 (2147483648      & 0xFFFFFFFF) === -2147483648
 (-2147483649     & 0xFFFFFFFF) ===  2147483647
 (0x80000000      & 0xFFFFFFFF) === -2147483648
 (3000000000.5    & 0xFFFFFFFF) === -1294967296

Also. Bitwise operations don't "floor". They truncate, which is the same as saying, they round closest to 0. Once you go around to negative numbers, Math.floor rounds down while bitwise start rounding up.

As I said before, Math.floor is safer because it operates with 64bit floating numbers. Bitwise is faster, yes, but limited to 32bit signed scope.

To summarize:

  • Bitwise works the same if you work from 0 to 2147483647.
  • Bitwise is 1 number off if you work from -2147483647 to 0.
  • Bitwise is completely different for numbers less than -2147483648 and greater than 2147483647.

If you really want to tweak performance and use both:

function floor(n) {
    if (n >= 0 && n < 0x80000000) {
      return n & 0xFFFFFFFF;
    }
    if (n > -0x80000000 && n < 0) {
      return (n - 1) & 0xFFFFFFFF;
    }
    return Math.floor(n);
}

Just to add Math.trunc works like bitwise operations. So you can do this:

function trunc(n) {
    if (n > -0x80000000 && n < 0x80000000) {
      return n & 0xFFFFFFFF;
    }
    return Math.trunc(n);
}

  • The specs say that it is converted to an integer:

    Let lnum be ToInt32(lval).

  • Performance: this has been tested at jsperf before.

note: dead link to spec removed