Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a shift by 0 truncate the decimal?

I recently found this piece of JavaScript code:

Math.random() * 0x1000000 << 0

I understood that the first part was just generating a random number between 0 and 0x1000000 (== 16777216).

But the second part seemed odd. What's the point of performing a bit-shift by 0? I didn't think that it would do anything. Upon further investigation, however, I noticed that the shift by 0 seemed to truncate the decimal part of the number. Furthermore, it didn't matter if it was a right shift, or a left shift, or even an unsigned right shift.

> 10.12345 << 0
10
> 10.12345 >> 0
10
> 10.12345 >>> 0
10

I tested both with Firefox and Chrome, and the behavior is the same. So, what is the reason for this observation? And is it just a nuance of JavaScript, or does it occur in other languages as well? I thought I understood bit-shifting, but this has me puzzled.

like image 762
voithos Avatar asked Aug 25 '12 20:08

voithos


People also ask

What is truncate decimal?

To truncate a number, we miss off digits past a certain point in the number, filling-in zeros if necessary to make the truncated number approximately the same size as the original number. To truncate a number to 1 decimal place, miss off all the digits after the first decimal place.

What does trunc mean in Math?

trunc() The Math. trunc() function returns the integer part of a number by removing any fractional digits.


2 Answers

You're correct; it is used to truncate the value.

The reason >> works is because it operates only on 32-bit integers, so the value is truncated. (It's also commonly used in cases like these instead of Math.floor because bitwise operators have a low operator precedence, so you can avoid a mess of parentheses.)

And since it operates only on 32-bit integers, it's also equivalent to a mask with 0xffffffff after rounding. So:

0x110000000      // 4563402752
0x110000000 >> 0 // 268435456
0x010000000      // 268435456

But that's not part of the intended behaviour since Math.random() will return a value between 0 and 1.

Also, it does the same thing as | 0, which is more common.

like image 149
Ry- Avatar answered Oct 13 '22 10:10

Ry-


Math.random() returns a number between 0 (inclusive) and 1 (exclusive). Multiplying this number with a whole number results in a number that has decimal portion. The << operator is a shortcut for eliminating the decimal portion:

The operands of all bitwise operators are converted to signed 32-bit integers in big-endian order and in two's complement format.

The above statements means that the JavaScript engine will implicitly convert both operands of << operator to 32-bit integers; for numbers it does so by chopping off the fractional portion (numbers that do not fit 32-bit integer range loose more than just the decimal portion).

And is it just a nuance of JavaScript, or does it occur in other languages as well?

You'll notice similar behavior in loosely typed languages. PHP for example:

var_dump(1234.56789 << 0);
// int(1234)

For strongly types languages, the programs will usually refuse to compile. C# complains like this:

Console.Write(1234.56789 << 0);
// error CS0019: Operator '<<' cannot be applied to operands of type 'double' and 'int'

For these languages, you already have type-casting operators:

Console.Write((int)1234.56789);
// 1234
like image 13
Salman A Avatar answered Oct 13 '22 10:10

Salman A