I am trying to translate simple JS code to C and/or Perl but I found a discrepancy in behaviour when doing arithmetic operations (+ - * / << >>) on integers and the result overflows. I need to simulate JS exactly, even the overflows! JS variables are not explicitly BigInt but just JS var.
JS (via node.js or Firefox's developer tools' console):
function calc(a, b){
return (a<<b) + (a<<b);
}
var x = calc(1, 30);
result:
2147483648
C:
#include <stdio.h>
#include <stdint.h>
int main(void){
int32_t lop = 1<<30; //1073741824;
int32_t rop = 1<<30; //1073741824;
int32_t res = lop + rop;
printf("1<<30 + 1<<30 : %d\n", res);
}
result:
1<<30 + 1<<30 : -2147483648
Perl:
sub to32bit { unpack("l", pack("L", $_[0])) } # Corion @ PerlMonks
print to32bit(to32bit(1<<30)+to32bit(1<<30));
result:
-2147483648
Am I right that there is a discrepancy or am I doing things wrong?
How to get this right?
As I said I need to emulate JS's exact behaviour in C/Perl so I don't want to fix JS code but adjust C/Perl code to do the same as JS.
See also related discussion at https://perlmonks.org/?node_id=11155911
Edit Feb/2024: There is now CPAN module Math::JS (at https://metacpan.org/pod/Math::JS) by Sisyphus.
((a<<b) + (a << b)) | 0that will force the answer to be the 32 bit signed you expect2147483648is not a signed 32-bit value, it is one unit too big. So you could used unsigned values, or 64-bit signed ints.