5

I know that numbers in JavaScript are stored in IEEE-754 format. But when we use integers, particularly bitwise operators, they're represented as two's complement with 32 bits.

So -1 would be 0xFFFFFFFF. But (-1).toString(2) is -1. And -1 >>> 31 is 1, that's right, but -1 >>> 32 must be 0, however it's 4294967295. And -1 << 32 must be 0, but it is -1.

Why do bitwise operations work in this way? And toString() shows number with sign -, why this minus is not in sign bit? Also why -1 >> 0 is -1, but -1 >>> 0 is 4294967295? I know what is the difference between >> and >>>, but the second operand is 0, so I can't understand why these operations work in different ways.

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
  • There's a [good discussion here](https://stackoverflow.com/questions/16155592/negative-numbers-to-binary-string-in-javascript) – Mark Feb 19 '20 at 16:07
  • MDN has good documentation on Bitwise operators in a JavaScript environment: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators – Daniel Lowman Feb 19 '20 at 16:10
  • @DanielLowman I have already read it. But I still don't understand why -1 >>> 32 is not 0? We shift it 32 times and add 32 zeros, so it should be 0 – Sergei Martianov Feb 19 '20 at 16:14

1 Answers1

3

Difference between >>> and >>

In an arithmetic shift, the sign bit is extended to preserve the signedness of the number.

-1 in 8 bit is 11111111 -2 is 11111110 ...

This is handled like that because if you count to the highest possible number +1, the lowest possible number will be shown (8 bit: 01111111 +1 = 10000000), Thats why 111111111 is -1

Logical right shift, however, does not care that the value could possibly represent a signed number; it simply moves everything to the right and fills in from the left with 0s.

so here, -1 >>> pushes the 11111111 one to the right so the "-" sign gets lost and the highest positive number 0111111 (in 8 bit) is shown

Also the reason why -1 >> 0 equals -1 is because 11111111 >> 0 does literally add nothing while -1 >>> 0 still moves everything and fills the left bits with 0, each step you raise this "0" will half the value until 0. You can try -1 >>> 31 to see it gets 1

Updater
  • 459
  • 2
  • 13
  • Yes, I know. But -1 is 0xFFFFFFFF (or 32 `1`), so -1 >>> 32 sould be 0, shouldn't it? – Sergei Martianov Feb 19 '20 at 16:09
  • Yeah, when you >>> with the amount of bits used, it just restarts the process like it would be >>> 0 again, 33 halfs it again and so on – Updater Feb 19 '20 at 16:23
  • Oh, I realize. So when we do any N-bits shift and N >= 32, it will be equal to (N % 32)-bits shift? – Sergei Martianov Feb 19 '20 at 16:35
  • 1
    yeah exactly :) – Updater Feb 19 '20 at 16:57
  • I'm not sure about JavaScript, but in C, shifting by more bits than the size of CPU registers is *undefined behavior*. Since C bitshift instructions translates into CPU assembly instructions, it becomes hardware-dependent. For example, Intel x86 `shr` / `shl` instructions use only 5 least significant bits of argument on 32bit CPU, or 6 LSBs on 64bit. That's why you get `% 32` behavior (`2 ^ 5 = 32`). However, It doesn't mean that other CPUs (arm, ppc, mibs, etc.) will do the same (maybe they will, but it is not guaranteed). – PooSH Feb 24 '20 at 12:38