Using Bitwise or 0 to Floor a Number

Using bitwise OR 0 to floor a number

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

How does x|0 floor the number in JavaScript?

Because, according to the ECMAScript specifications, bitwise operators operators call ToInt32 on each expression to be evaluated.

See 11.10 Binary Bitwise Operators:

The production A : A @B, where @ is one of the bitwise operators in
the productions above, is evaluated as follows:

  1. Evaluate A.

  2. Call GetValue(Result(1)).

  3. Evaluate B.

  4. Call GetValue(Result(3)).

  5. Call ToInt32(Result(2)).

  6. Call ToInt32(Result(4)).

  7. Apply the bitwise operator @ to Result(5) and Result(6). The result is a signed 32 bit integer.

  8. Return Result(7).

Flooring numbers in JavaScript: ~~n, n|0 or Math.floor(n)?

Be clear to the next person looking at your code and use Math.floor().

The performance gain of 1%-40% isn't really worth it, so don't make your code confusing and hard to maintain.

Bitwise OR operation with 0b transform a given number in negative

Bitwise operators implicitly convert their operands to 32-bit integers (signed or unsigned, depending on operator). In process, numbers with more than 32 bits get their most significant bits discarded:

Before: 11100110111110100000000000000110000000000001
After: 10100000000000000110000000000001

The only exception of this rule is (relatively) new kid on the primitive block, BigInt type: all the bitwise ops (&, |, ^) and almost all the shifts are overloaded for that type.

This opens a way out of your problem: just use BigInt instead of plain number, either explicitly, like this:

const bigIntee = BigInt(1071698660929); // note no `new` here!

... or, if you actually have to use literal, by appending n to it:

const bigIntee = 1071698660929n; // also works

Note that if one operand is BigInt, another should be BigInt as well. So this...

bigIntee | 0

... will make JS angry with your pathetic attempts of getting back to happy type-anarchy times of 90s. To be more specific, you'll get a TypeError thrown right at you:

Cannot mix BigInt and other types, use explicit conversions

This is easily fixable, though: just apply either of aforementioned conversion tricks to the second operand as well.

bigIntee | 0n 
// or bigIntee | BigInt(0)

Both works. Disregard 0 being, well, not really a Biggus Integerus kind; type safety reigns here.

Still, there's a problem: >>> (unsigned right shift operator) cannot be used on BigInts. If you attempt to go with it, you'll get a pretty specific error:

bigIntee >>> 0n
// Uncaught TypeError: BigInts have no unsigned right shift, use >> instead

... which makes total sense (and us wishing all the errors thrown by JS were that specific).

Is it possible to test if a number is either even or '1', using only bitwise operators?

Although I would not recommend to do this at all, but I was able to achieve it in C, but with only making a to be anunsigned char. It could work with others too, but that would lengthen the condition.

#include <stdio.h>

int main() {
for (unsigned char a = 0; a < 255; a++) {
if ((~a & 1) | (1 >> (a & 0x0E | a >> 4)))
printf ("%d is even or 1\n", a);
else
printf("%d is odd\n", a);
}
return 0;
}

(~a & 1) will yield 1 if a is even. (a & 0x0E | a >> 4) will yield 0 when a is either 1 or 0. Therefore in those cases (1 >> (a & 0x0E | a >> 4))) will be (1 >> 0) which is 1, otherwise the shift value is between 1 and 15 so making the expression 0.

My initial approach was (1 >> (a >> 1)), but soon realized this cause shift overflow, since the shift amount exceed the max possible. And not just raising that warning, but actually falsely recognize every n * 64 + 1 values as even. So the more complicated approach is there to limit the shift amount to be less than 64 by OR -ing a upper 4 bit with its lower 4 bit, but setting the LSB to 0. This resulting number is <= 15 and only 0 when a is 1 or 0 just as needed.

C program to clear nth bit of a number using bitwise and operator

Bitwise operations are performed on all bits.

The result of 0 << time is timeth bit set to zero, and all other bits are zero. So all bits are zero. Bitwise and with zero will always result in zero.

Contrary, the result of 1 << time is timeth bit set to one, and all other bits are zero. After bitwise negation, the result is timeth bit set to zero, and all other bits are one. Bitwise and will zero out only timeth bit.

How removing decimal parts with bitwise operators work?

With |, its two operators are converted to integers through the NumberBitwiseOp operation, which calls ToInt32 on both operators, whose process is:

The abstract operation ToInt32 takes argument argument. It converts argument to one of 232 integer values in the range -231 through 231 - 1, inclusive. It performs the following steps when called:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, +0, -0, +∞, or -∞, return +0.
  3. Let int be the Number value that is the same sign as number and whose magnitude is floor(abs(number)).
  4. Let int32bit be int modulo 2 ** 32.
  5. If int32bit ≥ 2 ** 31, return int32bit - 2 ** 32; otherwise return int32bit.

~, or bitwise NOT, does the same sort of thing, by calling ToInt32 on its operator.

Using x | 0 will remove the decimal part of x (via ToInt32) and flip no bits, so it's as if just the decimal part was removed.

Using ~x will remove the decimal part of x and flip all of its bits. Using ~~x will do the same, but flip the bits twice, so the result is as if all that was done to the original expression was drop the decimal part.

Computing the floor of log₂(x) using only bitwise operators in C

This gets the floor of logbase2 of a number.

int ilog2(int x) {

int i, j, k, l, m;
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
x = x | (x >> 16);

// i = 0x55555555
i = 0x55 | (0x55 << 8);
i = i | (i << 16);

// j = 0x33333333
j = 0x33 | (0x33 << 8);
j = j | (j << 16);

// k = 0x0f0f0f0f
k = 0x0f | (0x0f << 8);
k = k | (k << 16);

// l = 0x00ff00ff
l = 0xff | (0xff << 16);

// m = 0x0000ffff
m = 0xff | (0xff << 8);

x = (x & i) + ((x >> 1) & i);
x = (x & j) + ((x >> 2) & j);
x = (x & k) + ((x >> 4) & k);
x = (x & l) + ((x >> 8) & l);
x = (x & m) + ((x >> 16) & m);
x = x + ~0;
return x;
}

Why Date.now() | 0 not same as Date.now()

Bitwise operators operate on bits as represented by 32 zeros and/or ones. If the number being operated on is outside this range, the result will likely be unintuitive.

For bitwise OR, this limit is reached once the number is 2 ** 31 - 1:

const test = num => console.log((num | 0) === num);

test(2 ** 31 - 1)

test(2 ** 31)

test(2 ** 31 + 1)

Comparing floats/doubles bitwise after floor/ceil

fabs(floor(a) - floor(b)) < 0.0001 only if floor(a) == floor(b), as long as you're in the range of integers that doubles can accurately represent: Does casting to an int after std::floor guarantee the right result?



Related Topics



Leave a reply



Submit