Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

decimal to binary

by divyaimca (Initiate)
on Jan 09, 2012 at 06:21 UTC ( #946947=perlquestion: print w/replies, xml ) Need Help??

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

HI, I am new to perl. I was converting the decimal to binary for numbers below 256. I got a way to do this:

#!/usr/bin/perl use warnings; use strict; print " Enter a number between 0 to 256 : "; my $dec = <STDIN>; my $a = ($dec & 128) <=> 0; my $b = ($dec & 64) <=> 0; my $c = ($dec & 32) <=> 0; my $d = ($dec & 16) <=> 0; my $e = ($dec & 8) <=> 0; my $f = ($dec & 4) <=> 0; my $g = ($dec & 2) <=> 0; my $h = ($dec & 1) <=> 0; print " The entered decimal number in binary is : ",$a.$b.$c.$d.$e.$f. +$g.$h," \n";
I think its ok. But I am wondering if the number is greater than 256 ??

Replies are listed 'Best First'.
Re: decimal to binary
by GrandFather (Saint) on Jan 09, 2012 at 06:57 UTC

    Good for using strictures (strict and warnings), but not so good for resorting to a large number of variables to store the bits. An array is a much better way to store a bunch of related data:

    #!/usr/bin/perl use warnings; use strict; print "Enter a number between 0 to 256 : "; my $dec = <STDIN>; my @bits; $bits[7] = ($dec & 128) <=> 0; $bits[6] = ($dec & 64) <=> 0; $bits[5] = ($dec & 32) <=> 0; $bits[4] = ($dec & 16) <=> 0; $bits[3] = ($dec & 8) <=> 0; $bits[2] = ($dec & 4) <=> 0; $bits[1] = ($dec & 2) <=> 0; $bits[0] = ($dec & 1) <=> 0; printf "The entered decimal number in binary is : %s\n", join '', reve +rse @bits;

    That makes it easier to manipulate the bits as a group which is quite an advantage when we come to printing it. However there are still too many lines of repeated code. We can fix that by calculating the bit mask from the bit index:

    ... my @bits; $bits[$_] = ($dec & 2 ** $_) <=> 0 for 0 .. 7; printf "The entered decimal number in binary is : %s\n", join '', reve +rse @bits;

    But none of that addresses your question about (I presume) handling numbers greater than 256. However, now we have an array we can use whatever number of bits we need so:

    ... my @bits; while ($dec || ! @bits) { push @bits, $dec & 1; $dec >>= 1; } printf "The entered decimal number in binary is : %s\n", join '', reve +rse @bits;
    True laziness is hard work

      Thank you grandfather for the tips. You have used some keywords unknown to me but are self explainable. But I didn't understand the logic for converting decimals greater than 256. I just started the Perl for beginners ..

        The key is $dec >>= 1; which shifts $dec one bit right - that is, it moves all the bits one position down and the previous least significant bit "drops off the end". A 0 bit is shifted in as the most significant bit so eventually all the one bits have been shifted out and the while loop ends.

        The || !@bits makes sure that there is at least one bit in @bits by executing the loop once when $dec is 0.

        I'd guess join and maybe push are new to you. I've provided links to documentation for them.

        True laziness is hard work
Re: decimal to binary
by Khen1950fx (Canon) on Jan 09, 2012 at 07:34 UTC
    I used dec2bin from the Perl Cookbook.
    sub dec2bin { my $str = unpack('B32', pack('N', shift)); $str =~ s/^0+(?=\d)//; return $str; }
    For example:
    #!/usr/bin/perl -l use strict; use warnings; $|=1; my(@dec) = qw(1 2 3 4 5 6 7 8 9 10 16 32 64 100 256 512 1000 1024); foreach my $dec (@dec) { print dec2bin( $dec ); } sub dec2bin { my $str = unpack('B32', pack('N', shift)); $str =~ s/^0+(?=\d)//; return $str; }
Re: decimal to binary
by mbethke (Hermit) on Jan 09, 2012 at 06:51 UTC

    Your function will only use the lower 8 bits and ignore anything above that. For an alternative, it depends on what you want to do: get a working solution or learn about binary arithmetic and how to deal with bits "by hand". For everything up to 32 or 64 bit depending on your CPU, the following will do:

    perl -e 'printf "%b\n", <STDIN>'

    If you want to do it yourself, consider using a loop starting with a bitmask of 0x80000000 that you right-shift in each step after masking the input value and outputting the corresponding bit.

Re: decimal to binary
by Marshall (Canon) on Jan 09, 2012 at 11:06 UTC
    I think the question has been answered, but I'll post a couple of other formulations for you. Sometimes seeing other programming techniques is helpful.

    This is from a CRC program that was coded in assembly, C and Perl. The relevant part prints the 16 bit CRC values.

    The Perl code:
    A lab requirement was to print the 16 bits like: 0101 1011 1100 0001

    printf "The CRC Bytes (binary) : %04b %04b %04b %04b\n", $CRC_byte1>>4, $CRC_byte1 & 0xF, $CRC_byte2>>4, $CRC_byte2 & 0xF;
    In Perl, there is a %b "format spec" for printf - described on the sprintf man page. I didn't mess with a loop, and rather just used some simple binary shift and "and" operations to extract each group of 4 bits (a hex digit actually) from the 2 bytes comprising the 16 bit CRC value. In a case like this, with fixed format (always 16 binary digits), no loop is needed. Oh, I should point out that it is known that $CRC_byte1 and $CRC_byte2 only use 8 bits each.

    The C code:
    There is no %b format spec in standard C. So I did it a bit differently...

    void dump_16bits(unsigned int any_16bits) { int i; for (i=0; i<16; i++) { if (i%4==0 )printf (" "); printf ("%c", (any_16bits & 0x8000) ? '1':'0'); any_16bits <<=1; #a keft shift 1 bit } }
    This uses the modulo operator (%) to put a space in every 4 binary digits. The printf statement here prints '1' or '0' depending upon the most significant bit (specifically the 2**15 bit)

    The modulo operator (%) and the ternary operator (any_16bits & 0x8000) ? '1':'0' both exist in Perl also and you may on occasion find a use for them. In this case, the Perl version if this was "translated as directly from C to Perl" as possible, would be almost identical.

    This was a demo for my lab students and I used different techniques on purpose. I'll spare you the assembly code!

    My purpose was just to demo some other techniques for you.

Re: decimal to binary
by Anonymous Monk on Jan 09, 2012 at 06:46 UTC

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (3)
As of 2022-07-01 13:35 GMT
Find Nodes?
    Voting Booth?
    My most frequent journeys are powered by:

    Results (98 votes). Check out past polls.