Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl shift bit problem

Tags:

perl

I have problem when try to shift bit for a negative number with Perl. For example:

printf("%d", (-10) >> 2);

This method print: 1073741821

With same condition, when I try to do it with Javascript:

document.write('test: ' + (-10 >> 2) + '<br>');

The output is -3

I would like to understand the different between Perl and Javascripts. Does Perl have problem with shifting bit for a negative number?

Thank you very much.

like image 714
Minh Le Avatar asked Dec 02 '22 04:12

Minh Le


2 Answers

Perl uses unsigned binary right shift. If Perl runs on a 32-bit architecture, you get the following:

-10 == -0xa == 0xfffffff6
0xfffffff6 >> 2 == 0x3ffffffd == 1073741821

Unsigned binary right shift means that the highest (rigtmost) bits of the result become 0.

JavaScript uses sign-extending binary right shift. JavaScript shifts always treat both the input and the output as 32 bit integers. So you get:

-10 == -0xa == 0xfffffff6
-3 == -0x3 == 0xfffffffd
0xfffffff6 >> 2 == 0xfffffffd == -3

Sign-extending binary right shift means that the highest (rigtmost) bits of the result get copied from the highest bit of the original value.

As Tim Henigan said in his answer, it's possible to get sign-extending binary right shift from Perl, by specifying use integer;. Example:

{ use integer;
  printf "%d 0x%x\n", (-10) >> 2, (-10) >> 2;  #: -3 0xfffffffd
}
printf "%d 0x%x\n", (-10) >> 2, (-10) >> 2;  #: 1073741821 0x3ffffffd
like image 93
pts Avatar answered Dec 04 '22 22:12

pts


If it is an option, you may correct this signed right shift with use integer.

For example:

use integer;
printf("%d", (-10) >> 2);

...produces the correct result (-3).

From perlop:

Note that both "<<" and ">>" in Perl are implemented directly using "<<" and ">>" in C. If use integer (see Integer Arithmetic) is in force then signed C integers are used, else unsigned C integers are used. Either way, the implementation isn't going to generate results larger than the size of the integer type Perl was built with (32 bits or 64 bits).

For more info, see the integer perldoc.

like image 26
Tim Henigan Avatar answered Dec 04 '22 22:12

Tim Henigan