Bitwise operations on large numbers [duplicate] - javascript

This question already has an answer here:
Bitwise OR operation with 0b transform a given number in negative
(1 answer)
Closed 7 months ago.
This works as expected:
> 0b1111
15
> 0b1111 & 0b1111
15
But this doesn't:
> 0b11111111111111111111111111111111
4294967295
> 0b11111111111111111111111111111111 & 0b11111111111111111111111111111111
-1
What's going on here? And how can I safely perform bitwise operations on large (up to 2^32) numbers in Javascript?
Update: This is below Number.MAX_SAFE_INTEGER so I don't believe there should be a loss of precision.

What's going on here?
JavaScript's bitwise operators will interpret the result as a signed 32-bit number (one exception is the >>> operator), but apart from that, the result is correct.
And how can I safely perform bitwise operations on large (up to 2^32) numbers in Javascript?
Apply >>> 0 to the result so the result is interpreted as an unsigned 32 bit number:
let res = (0b11111111111111111111111111111111
& 0b11111111111111111111111111111111) >>> 0;
console.log(res);

Related

I do not understand about bitwise operator in Javascript

I am student studying programming.
As far as I know, Javascript saves number as float.
However, bitwise operator in Javascript run as a type of number is integer.
For instance,
> 1 | 2 // -> 3
> 2 << 4 // -> 32
How is it possible?
I find official documentation(mdn web docs), but I can not find the reason.
The bitwise operators in JavaScript convert numbers to 32-bit integers before performing the operation. This means that even though JavaScript saves numbers as floats, the bitwise operators treat them as 32-bit integers. This is why you are able to use the bitwise operators on numbers and get integer results.
As #rviretural_001 mentioned, JavaScript does some automatic conversions by spec. For example, in addition to IEEE 754 doubles to 32 signed integers:
0 == '0' // true
String to Integer (Shift Right)
'4' >> 1 // 2
Converting to Integer (Bitwise OR)
'1.3' | 0 // 1
This last one was used in asm.js for 32 signed integers
just to contribute to the answers above note that the conversion of a floating-point number to an integer is done by removing the fractional part of the number.
For example, if you have the number 4.5 and you use a bitwise operator on it, JavaScript will convert it to the integer 4 before performing the operation.
This tutorial might help you to find out more https://www.programiz.com/javascript/bitwise-operators
Also note that performing bitwise operations on floating-point numbers can lead to unexpected results. This is due to the way floating-point numbers are represented in memory. So, it's recommended to avoid using bitwise operators on floating-point numbers in JavaScript.

Different calculation result [duplicate]

This question already has answers here:
Bitshift in javascript
(4 answers)
Closed 1 year ago.
Explain to me why the result of the following calculation is different:
Python:
tmp = 4235635936 << 0 #4235635936
JS
let tmp = 4235635936 << 0 // -59331360
Question - how do I get the same result in python as in js ?
The binary representation for both numbers is the same. One is signed, the other is unsigned.
>>> struct.pack("<i", -59331360)
b'\xe0\xacv\xfc'
>>> struct.pack("<I", 4235635936)
b'\xe0\xacv\xfc'
>>>
in JS, the bitwise operators and shift operators operate on 32-bit ints, and your example overflows the 32-bit capacity.
In Python there's no capacity limit for integers, so you get the actual value.

Left shift results in negative numbers in Javascript

I'm having trouble understanding how shifting works. I would expect that a and b would be the same but that's not the case:
a = 0xff000000;
console.log(a.toString(16));
b = 0xff << 24;
console.log(b.toString(16));
resulting in:
ff000000
-1000000
I came to this code while trying to create a 32bit number from 4 bytes.
Bitwise operators convert their operands to signed 32 bit numbers. That means the most significant bit is the sign bit, which gives you only 31 bits for the number value.
0xff000000 by itself is interpreted as 64bit floating point value. But truncating this to a 32bit signed integer produces a negative value since the most significant bit is 1:
0xff000000.toString(2);
> "11111111000000000000000000000000"
(0xff000000 | 0).toString(16)
> -1000000
According to Bitwise operations on 32-bit unsigned ints? you can use >>> 0 to convert the value back to an unsigned value:
0xff << 24 >>> 0
> 4278190080
From the spec:
The result is an unsigned 32-bit integer.
So it turns out this is as per the spec. Bit shift operators return signed, 32-bit integer results.
The result is a signed 32-bit integer.
From the latest ECMAScript spec.
Because your number is already 8 bits long, shifting it left by 24 bits and then interpreting that as a signed integer means that the leading 1 bit is seen as making it a negative number.

Why does the bitwise operator OR truncate the value in this example? [duplicate]

This question already has answers here:
Why does OR 0 round numbers in Javascript?
(3 answers)
Closed 5 years ago.
The Mozilla JavaScript Guide has this to say about the bitwise OR operator:
"Bitwise OR: Returns a zero in each bit position for which the corresponding bits of both operands are zeros."
However, when operand b is 1, the bitwise operator OR in the example below rounds up a. This is something I cannot wrap my head around. Also, seeing as a returns a non rounded number, it is also not clear to me how the bitwise operator truncates it down to two digits.
var a = Math.random()*100;
console.log(a);
console.log(a | 1);
Insightful explanations are very welcome.
The hidden factor here is bitwise operators cast the number to an integer before being applied. That is why the number gets rounded. The cast truncates any fractional part.
The bitwise OR itself then simply sets the first bit to 1. So may or may not increase the truncated number by 1 depending on whether it was odd or even after the truncation.
So it's not rounding it up in all cases - just 50% of the time.

How does the expression "float | 0" produces an integer? [duplicate]

This question already has answers here:
Using bitwise OR 0 to floor a number
(7 answers)
Closed 8 years ago.
Please describe how does 5.55 | 0 produces 5 in JavaScript. I want to know what is happening in this bitwise operating. Thanks!
The bitwise operators in Javascript automatically coerce their arguments to 32-bit integer values by dropping the fraction and any high-order bits beyond 32. So
5.55 | 0
is treated like:
5 | 0
The operands of bitwise operations are always converted to signed 32-bit integers in big-endian order and in two's complement format.
That would be
00000000000000000000000000000101
or 00000000000000000000000000000000
------------------------------------
00000000000000000000000000000101

Categories