Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Left shift results in negative numbers in Javascript

Tags:

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.

like image 529
benathon Avatar asked Jan 03 '19 22:01

benathon


People also ask

Can you left shift by a negative number?

The left shift and right shift operators should not be used for negative numbers. The result of is undefined behaviour if any of the operands is a negative number. For example results of both 1 >> -1 and 1 << -1 is undefined. If the number is shifted more than the size of integer, the behaviour is undefined.

Can shift operator be applied to negative numbers?

Operator >> called Signed right shift, shift all the bits to right a specified number of times. Important is >> fills leftmost sign bit (Most Significant Bit MSB) to leftmost bit the after shift. This is called sign extension and serves to preserve the sign of negative numbers when you shift them right.

How do you shift a negative number?

Right Shifts For signed numbers, the sign bit is used to fill the vacated bit positions. In other words, if the number is positive, 0 is used, and if the number is negative, 1 is used. The result of a right-shift of a signed negative number is implementation-dependent.

What does a left shift do to a number?

The number to the left of the operator is shifted the number of places specified by the number to the right. Each shift to the left doubles the number, therefore each left shift multiplies the original number by 2. Use the left shift for fast multiplication or to pack a group of numbers together into one larger number.


2 Answers

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.

like image 165
Felix Kling Avatar answered Oct 05 '22 15:10

Felix Kling


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.

like image 42
GregL Avatar answered Oct 05 '22 16:10

GregL