I need to perform certain operations with bitwise operators, let's say we have this 40 bit unsigned integer:
1071698660929
when I apply to it a OR
operator and an unsigned right shift operator I got this negative integer
Input: (1071698660929 >>> 0) | 0b0
Output: -2043163071
I noticed that as long as the number is 31 bit long I don't have any problem adding a 0B0
but when the number is greater than 31 bit it becomes negative even though I'm using the unsigned right shift operator:
32 bits binary return -1
: (0b11111111111111111111111111111111 >>> 0) | 0
31 bits binary return 2147483647
: (0b1111111111111111111111111111111 >>> 0) | 0
So I have a couple of questions:
Number.MAX_SAFE_INTEGER.toString(2).length
so I'm within the integer safe boundaries.(1071698660929 >>> 0) | 0b0
returns
1071698660929
instead of -2043163071
?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).