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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With