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

Hello Monks,

I am trying to convert decimals to binary and binary to decimals. By using pack and unpack I can convert all positive numbers, in case that a number is negative the process needs to be changed.

Update: Solution with pack and unpack at the end of the question.

Sample of working code demonstrating the problem:

#!/usr/bin/perl use strict; use warnings; my $possitive = 3; my $negative = -3; print "My possitive decimal: ".$possitive."\n"; print "My negative decimal: ".$negative."\n"; my $possitive_b = dec2bin($possitive,8); my $negative_b = dec2bin($negative,8); print "Possitive binary: ".$possitive_b."\n"; print "Negative binary: ".$negative_b."\n"; my $possitive_d = bin2dec($possitive_b); my $negative_d = bin2dec($negative_b); print "Possitive_binary back to decimal: ".$possitive_d."\n"; print "Negative_binary back to decimal: ".$negative_d."\n"; sub dec2bin { my $bits = shift; my $possition = shift; my $str = unpack("B32", pack("N", $bits)); $str = substr $str, -$possition; return $str; } sub bin2dec { return unpack("N", pack("B32", substr("0" x 32 . shift, -32))); } __END__ My possitive decimal: 3 My negative decimal: -3 Possitive binary: 00000011 Negative binary: 11111101 Possitive_binary back to decimal: 3 Negative_binary back to decimal: 253

As we can see the negative -3 became 253.

So is there a way to convert the negative decimals to binary and back to decimal?

Answer for future reference:
#!/usr/bin/perl use strict; use warnings; use Data::Dumper; sub dec2bin { my $bits = shift; my $str = unpack("B8", pack("c", $bits)); return $str; } sub bin2dec { return unpack("c", pack("B8", substr("0" x 8 . shift , -8))); } my $floating2binary = dec2bin(-127); print "Binary from floating: ".$floating2binary."\n"; my $binary2floating = bin2dec($floating2binary); print "Binary from floating: ".$binary2floating."\n"; __END__ Binary from floating: 10000001 Binary from floating: -127
Seeking for Perl wisdom...on the process of learning...not there...yet!

Replies are listed 'Best First'.
Re: How to convert between decimal and binary for negative numbers?
by BrowserUk (Patriarch) on Sep 18, 2014 at 13:16 UTC

    Template 'N' is for unsigned 32-bit integers (ie. no negative values).

    You'll need to use 'l' or 'i' or 'j' for signed 32-bit integers. See the pack documentation to select the appropriate one for your purpose.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Hello BrowserUk

      Thank you for your time and effort to help me with my problem. Thank you for the tip.

      Based on my code if I am using an int size 32 bit works fine. But I was trying to get a solution for small negative numbers, no more than -127 which is the limit of 8 bit int. A tried a dew different solutions but none successfully so far, any ideas?

      #!/usr/bin/perl use strict; use warnings; my @array = (3,-3); foreach $_ (@array){ if ($_ < 0) { print "Value: $_ is negative\n"; my $negative_b = dec2bin($_,32,"i"); print "Negative binary: ".$negative_b."\n"; my $negative_d = bin2dec($negative_b,"i"); print "Negative_binary back to decimal: ".$negative_d."\n"; } else { print "Value: $_ is possitive\n"; my $possitive_b = dec2bin($_,8,"N"); print "Possitive binary: ".$possitive_b."\n"; my $possitive_d = bin2dec($possitive_b,"N"); print "Possitive_binary back to decimal: ".$possitive_d."\n"; } } sub dec2bin { my $bits = shift; my $possition = shift; my $template = shift; my $str = unpack("B32", pack($template, $bits)); $str = substr $str, -$possition; return $str; } sub bin2dec { my $bits = shift; my $template = shift; return unpack($template, pack("B32", substr("0" x 32 . $bits , -32 +))); } __END__ Value: 3 is possitive Possitive binary: 00000011 Possitive_binary back to decimal: 3 Value: -3 is negative Negative binary: 11111101111111111111111111111111 Negative_binary back to decimal: -3
      Seeking for Perl wisdom...on the process of learning...not there...yet!
        But I was trying to get a solution for small negative numbers, no more than -127 which is the limit of 8 bit int.

        If you want to pack 8-bit numbers, do not use 32-bit templates; nor 'B32'.

        Think! read, and think again.

        (Hint:8-bit signed numbers; 'B8' and 'c'...)


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: How to convert between decimal and binary for negative numbers?
by Laurent_R (Canon) on Sep 18, 2014 at 17:52 UTC
    Hi, if your numbers are integers (all your examples are integers), it might be easier to use the %b and %d modifiers of the printf or sprintf functions, as shown in the following Perl one-liners:
    $ perl -e 'printf "%08b", 75' 01001011 $ perl -e 'printf "%032b", 4375' 00000000000000000001000100010111 $ perl -e 'printf "%d", 0b01001011' 75 $ perl -e 'printf "%08b", -75' 1111111111111111111111111111111111111111111111111111111110110101 $ perl -e 'printf "%d", 0b11111111111111111111111111111111111111111111 +11111111111110110101' -75

      Hello Laurent_R,

      Thank you for your time and effort replying to my question. I do have a solution for positive integers also with sprintf but I measured the process time, and using pack it is 50% faster. Even though that I am using subroutines, still is 50% faster. But thanks a lot for the suggestion, it is always nice to have alternatives.

      Seeking for Perl wisdom...on the process of learning...not there...yet!
        Yes, of course, I agree. If execution time is really critical, then I can easily believe that pack is faster, I have observed that myself quite a few times. But if execution time is not so crucial, then I would say that the time you spend writing relatively complicated subroutines using pack and unpack might not be worth the effort. An hour of a developer's working time is worth many many many CPU cycles. But this is of course your decision, based on your knowledge of the process.

        Writing the examples above using printf took me probably about 5 to 6 minutes, perhaps even less, I know that using pack will probably take me hours, because the syntax is quite complicated (or perhaps because I don't master it well enough, but that does not really change the net result). Being an independent consultant, I know what my time is worth, and I know that I will go for the smaller developer's time consuming option, except if high performance is really badly needed.

        Oh, and BTW,the solution I offered seems to work also with negative integers.