Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Difference between Perl and Java for << operator?

by davidfilmer (Sexton)
on Jul 29, 2021 at 22:43 UTC ( [id://11135504]=perlquestion: print w/replies, xml ) Need Help??

davidfilmer has asked for the wisdom of the Perl Monks concerning the following question:

Hello Masters! I am trying to liberate a Java program into Perl. It does a bunch of weird bitwise operations which I'm not very familiar with, but it seems the "<<"operator (left-shift) does not appear to be acting the same way. I have this bit of Java code, which is known to work as-expected:
public class hashTest { public static void main(String[] args) { long HIGH_BITS = 0xFFFFFFFF << 28; System.out.print( HIGH_BITS ); } }
RESULT: -268435456


In Perl, I rendered it like this:
#!/usr/bin/perl my $HIGH_BITS = 0xFFFFFFFF << 28; print( $HIGH_BITS );
RESULT: 4026531840



Can anyone see any reason why my Perl would not produce equivalent results as the Java code?

Thanks!

Replies are listed 'Best First'.
Re: Difference between Perl and Java for << operator?
by jwkrahn (Abbot) on Jul 29, 2021 at 23:51 UTC
    $ perl -le'my $HIGH_BITS = 0xFFFFFFFF << 28; print $HIGH_BITS' 1152921504338411520 $ perl -le'my $HIGH_BITS = unpack "l", pack "l", 0xFFFFFFFF << 28; pri +nt $HIGH_BITS; ' -268435456
Re: Difference between Perl and Java for << operator?
by eyepopslikeamosquito (Archbishop) on Jul 30, 2021 at 07:00 UTC

    JAVA RESULT: -268435456
    PERL RESULT: 4026531840

    Hope this simple little C program (compiled as C++) clarifies:

    // tbs2.cpp // Built with: g++ -o tbs2 -std=c++11 -Wall -O3 tbs2.cpp (and with 32- +bit int) #include <cstdio> int main(int argc, char* argv[]) { printf("d : %d\n", -268435456); printf("u : %u\n", -268435456); printf("x : 0x%x\n", -268435456); return 0; }

    Running this prints:

    d : -268435456 u : 4026531840 x : 0xf0000000
    Though all 32 bits are the same (11110000000000000000000000000000), what is displayed depends on whether you interpret them as a signed int (%d) or an unsigned int (%u) or an unsigned int as a hexadecimal number (%x). Java is displaying the 32-bit value as a signed int (-268435456). Perl is displaying the identical value as an unsigned int (4026531840).

    Sorry, I haven't used Java for twenty years, but Google tells me it has some sort of printf facility, so displaying your HIGH_BITS with Java printf with "%d" and "%u" - in addition to your System.out.print( HIGH_BITS ) - might be fun.

    My original basic test C++ program:

    // ANSI C++ 11: tbs1.cpp // Built with: g++ -o tbs1 -std=c++11 -Wall -O3 tbs1.cpp #include <cstdint> #include <iostream> int main(int argc, char* argv[]) { { int32_t HIGH_BITS = 0xFFFFFFFF << 28; std::cout << "int32 : HIGH_BITS = " << HIGH_BITS << "\n"; } { uint32_t HIGH_BITS = 0xFFFFFFFF << 28; std::cout << "uint32 : HIGH_BITS = " << HIGH_BITS << "\n"; } { int64_t HIGH_BITS = 0xFFFFFFFF << 28; std::cout << "int64 : HIGH_BITS = " << HIGH_BITS << "\n"; } { uint64_t HIGH_BITS = 0xFFFFFFFF << 28; std::cout << "uint64 : HIGH_BITS = " << HIGH_BITS << "\n"; } return 0; }

    displays:

    int32 : HIGH_BITS = -268435456 uint32 : HIGH_BITS = 4026531840 int64 : HIGH_BITS = 4026531840 uint64 : HIGH_BITS = 4026531840

    Further update: For cheap thrills, let's display the bits.

    // ANSI C++ 11: tbs4.cpp // Built with: g++ -o tbs4 -std=c++11 -Wall -O3 tbs4.cpp #include <cstddef> #include <cstdint> #include <cstdio> #include <iostream> #include <bitset> int main(int argc, char* argv[]) { printf("0xFFFFFFFF = %u\n", 0xFFFFFFFF); printf("0xF0000000 = %u\n", 0xF0000000); // This is the OP's 32-bit value HIGH_BITS const uint32_t HIGH_BITS = 0xFFFFFFFF << 28; std::cout << "HIGH_BITS = " << HIGH_BITS << "\n"; // Display all 32 bits 1 2 3 // 12345678901234567890123456789012 const std::bitset<32> b1{"11110000000000000000000000000000"}; std::cout << "b1 = " << b1 << "\n"; const std::bitset<32> b2{HIGH_BITS}; std::cout << "b2 = " << b2 << "\n"; return 0; }

    Running this produces:

    0xFFFFFFFF = 4294967295 0xF0000000 = 4026531840 HIGH_BITS = 4026531840 b1 = 11110000000000000000000000000000 b2 = 11110000000000000000000000000000

    64-bit Data Model References

    Updated: Minor changes were made to the originally posted code.

      Java doesn't support the %u format. Using a trick from StackOverflow gives the same results:
      public class HighBits { public static void main(String... argv) { long HIGH_BITS = 0xFFFFFFFF << 28; System.out.printf("%d\n", HIGH_BITS); System.out.printf("%d\n", HIGH_BITS & 0xFFFFFFFFL); } }
      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Difference between Perl and Java for << operator?
by GrandFather (Saint) on Jul 30, 2021 at 03:58 UTC

    -268435456 implies the JavaScript interpreter is using signed 32 bit numbers. The 4026531840 result implies Perl is representing the value as a 32 bit unsigned number.

    0xFFFFFFFF is a 32 bit value. If you shift it left by 28 bits you need 32 + 28 = 60 bits to represent the number so neither answer is actually correct in the sense that the true arithmetic result is given.

    With Perl you have the option of building perl (the interpreter) yourself and setting parameters like the size of various numeric types. An out of the box 64 bit Perl will use 64 bit integer variables and would give the correct result in this case.

    Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
      An out of the box 64 bit Perl will use 64 bit integer variables and would give the correct result in this case

      An interesting aside is that, for the OP's purposes, perl's ivsize is irrelevant, and this can be demonstrated using jwkrahn's perceptive solution :

      With 64-bit IVs:
      >perl -V:ivsize ivsize='8'; >perl -le "print unpack 'l', pack 'l', 0xFFFFFFFF << 28;" -268435456
      and with 32-bit IVs:
      C:\>perl -V:ivsize ivsize='4'; C:\>perl -le "print unpack 'l', pack 'l', 0xFFFFFFFF << 28;" -268435456
      Nor does $Config{longsize} make a difference - because the "l" template always specifies 32-bit.
      I believe the "i" template could also be used.
      According to the documentation, the "i" template could be specifying either 32-bit or 64-bit, depending upon $Config{intsize} - but I've never struck a perl where $Config{intsize} != 4.

      Cheers,
      Rob
      "implies the JavaScript interpreter"

      Java, not Javascript!

      - Ron
Re: Difference between Perl and Java for << operator?
by BillKSmith (Monsignor) on Jul 30, 2021 at 17:58 UTC
    The answer to your question is hidden in the documentation for Integer Arithmetic. You need use integer; if you want your result as a signed integer. (By default it is treated as an unsigned integer.) Note also, that your << 28 assumes that your perl is compiled for 32-bit integers.
    Bill
      Note also, that your << 28 assumes that your perl is compiled for 32-bit integers

      Well spotted - if you want to use the perl sub that the OP provided then:
      1) you will need to be running under the use integer pragma;
      and
      2) you will also need to be running a perl that was built with 32-bit integers.

      However, as has also been demonstrated, there are ways to obtain the desired result by doing a 0xFFFFFFFF << 28, that will work on both 32-bit integer and 64-bit integer builds.

      Cheers,
      Rob
Re: Difference between Perl and Java for << operator?
by Marshall (Canon) on Jul 29, 2021 at 23:26 UTC
    Tested on my 64 bit machine:
    use strict; use warnings; my $HIGH_BITS = 0xFFFFFFFF << 28; printf "%X\n", $HIGH_BITS; # prints: FFFFFFFF0000000 # each hex digit is 4 bits, 7 zeroes x4 = 28 bits left shifted
    Usually displaying something like that in decimal would be nonsensical.

    If you have an "all ones" in a 32 bit register, and you shift the contents 28 bits to the left, the high nibble will be "F". This will result in a negative value as viewed as a 2's complement number.

    Update: jwkrahn came up with the ball on this one:
    The trick is how to get Perl to display this value as signed integer.
    On Windows the quoting is a bit different, But this works on my Windows machine.

    >perl -le "my $HIGH_BITS = unpack "l", pack "l", 0xFFFFFFFF << 28; pri +nt $HIGH_BITS; " -268435456
    A simple: print $HIGH_BITS on my machine yields: 1152921504338411520 which of course is not right. This looks like the unsigned decimal value.
Re: Difference between Perl and Java for << operator?
by eyepopslikeamosquito (Archbishop) on Aug 09, 2021 at 09:15 UTC

    Since Java integers are always signed and with sizes:

    • short - 16 bits
    • int - 32 bits
    • long - 64 bits

    it seems to me the OP's Java code:

    long HIGH_BITS = 0xFFFFFFFF << 28;
    is ill-advised because (as has been pointed out multiple times in this thread) 0xFFFFFFFF << 28 is intrinsically a 32-bit value, while a Java long is 64-bits. Though the OP's code presumably "works", surely it ought to have been written as:
    int HIGH_BITS = 0xFFFFFFFF << 28;

    In case the OP is still listening, I won't be able to sleep at night until I learn the backstory as to why the Java code chose a long rather than an int. :)

Re: Difference between Perl and Java for << operator?
by LanX (Saint) on Jul 29, 2021 at 23:03 UTC
    Don't know much about Java, but

    > I have this bit of Java code, which is known to work as-expected:

    > RESULT: -268435456

    How can a negative result be considered expected?

    I think you should take care that both sides are unsigned integers of same size.

    FWIW I don't get your Perl result

    DB<16> say $x= 0xFFFFFFFF << 28 1152921504338411520

    so 64bit Perl seems to matter too.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

      It's an expected result if you assume signed 32 bit integer variables and your code is predicated on that assumption.

      Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
        as I said

        > > take care that both sides are unsigned integers of same size.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11135504]
Approved by LanX
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (5)
As of 2024-03-28 17:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found