Adler
Adler

Reputation: 79

Why in JavaScript expression 255 << 24 is a negative number?

When I run this code here:

console.log(255<<24==0xff000000)

I get a false instead of true. Why is that?

Upvotes: 4

Views: 2556

Answers (4)

Klaus
Klaus

Reputation: 724

Bitwise operations in javascript convert a number to a signed 32-bit integer, as described by T.J., so you only have 31 bits for safely comparing to a hex literal. If you want to preserve the unsigned number you really want (as opposed to casting your hex literal to the same negative number), do this:

255 * (1 << 24) == 0xff000000

Upvotes: 1

Esailija
Esailija

Reputation: 140228

0xff000000 doesn't specify bits of a 32-bit integer but a real number in hexadecimal base. For instance 0xff000000000000000000000 is 4.932417344027687e+27

All bitwise operations except >>> give the operand int32 semantics, with >>> giving uint32 semantics.

You may therefore use | 0 as a kind of int declaration or (int) cast:

255 << 24 == (0xff000000 | 0)
true

Upvotes: 1

loxxy
loxxy

Reputation: 13151

Look at it this way. This should look intuitive to you:

255<<24 == 0xff000000<<0          // Returns true

Bitwise operators work on integral numbers not on number types. Consider it as an equivalent to type casting as in other languages, where you happen to be putting a larger size number into smaller one & you lose stuff...

Javascript sacrifices precision to allow larger figures due to the floating point format, adopted.

So Javascript would lose the precision for 0xff000000, the same way as it did for 255.

Upvotes: 2

T.J. Crowder
T.J. Crowder

Reputation: 1074505

Because JavaScript numbers are IEEE-754 double-precision floating point, not 32-bit integers. So 0xff000000 is a large positive number (decimal 4,278,190,080), not a negative number as it would be if that were a signed 32-bit integer.

When you do <<, the number being shifted (255 in your case) is temporarily converted to a signed 32-bit integer for the purposes of doing the bit shift:

00000000000000000000000011111111
^\                             /
| \----- significant bits ----/
+------- sign bit

When we shift that 24 places left, a 1 bit ends up in the sign bit:

11111111000000000000000000000000
^\                             /
| \----- significant bits ----/
+------- sign bit

...and so the result ends up being negative, and gets turned back into a negative IEEE-754 number (-16,777,216 decimal). -16,777,216 is not equal to 4,278,190,080.

(The range of IEEE-754 double-precision floats is larger than the range of 32-bit signed integers. I'm not quite sure why I feel that's relevant, but I do, so I guess I'll leave it in the answer...)

Upvotes: 5

Related Questions