1

I need clarification on a problem that I have. I am currently trying to learn Perl using the Beginning Perl book provided by the "Learn Perl" portion of the Perl website. I am down to the ending of chapter 2 and I am currently having a hard time trying to understand the logic behind a solution that the book provided.

#!usr/bin/perl
#Ex2_3.plx
use warnings;


print "Please enter the value(less than 256) you wish to be converted into binary\n";
my $bin = <STDIN>;
chomp ($bin);

print "The binary value of $bin is : ", "\n";

#Use the bitwise and operator to determine the binary value:


print((128 & $bin) / 128);
print((64 & $bin) / 64);
print((32 & $bin) / 32);
print((16 & $bin) / 16);
print((8 & $bin) / 8);
print((4 & $bin) / 4);
print((2 & $bin) / 2);
print((1 & $bin) / 1);
print("\n");

I can't seem to understand the logic behind (128 & n) / 128 and so forth. While I do understand why is it that the code needs to go from 128 down to 1 I can't seem to grasp the solution after &. I feel bad because I normally hate looking at solutions, but this is all very intriguing to me, most other programming books put very small(if any) attention to bitwise operators. I will appreciate the help.

Alex_adl04
  • 562
  • 6
  • 17
  • Think about what 128, 64, 32, 16, 8, 4, 2, and 1 look like in their binary form and try ANDing them with some number 5 for instance and check the results. – Hunter McMillen Apr 23 '14 at 01:47
  • 2
    You might be interested in [this answer](http://stackoverflow.com/a/9203101/589924) which explains why `&` and `|` are used. – ikegami Apr 23 '14 at 02:06

2 Answers2

2

For example, decimal 128 is 10000000 in binary. &ing with this gives you the bit of the most significant bit. / 128 part is the same as shifting the bits to the right 7 times, since dividing the number by 2 is the same as shifting one bit to the right.

  10000000 (= 128)
& 10000110 (= 134)
  10000000

shifting 7 bits to the right, you get 1

Now, doing the same thing for 64

  01000000 (= 64)
& 10000110 (= 134)
  00000000

shifting 6 bits to the right (because 64 = 2^6), you get 0

Do this for the rest of the bits, you would get 1, 0, 0, 0, 0, 1, 1, 0, which would look 10000110 from the print statements.

The code from the book is basically the same as this:

#!/usr/bin/perl

use strict;
use warnings;

chomp(my $input = <STDIN>);

for (my $i = 7; $i >= 0; $i--) {
    print( (($input & (1 << $i)) >> $i) );
}

print "\n";
NigoroJr
  • 1,056
  • 1
  • 14
  • 31
  • I am starting to see the light, this is actually quite helpful.One thing that I can't seem to visualize: How would one know that dividing the result of ANDing the 2 numbers by the /128 or any of the others is the equivalent to the shifting? This is one of the things that I struggle the most as a beginner. I find it really hard to picture the means to a solution when trying to solve a problem even though I have less trouble understanding the syntax. – Alex_adl04 Apr 23 '14 at 04:49
  • I'm no expert in that area so I might be wrong, but I think that is the fundamental concept of base-n systems. Every time you shift a bit (i.e. a digit), you multiply or divide the number by n. For example, in decimal 100, 010, 001, you are dividing by 10 as you shift digits. In this case, 10 is the base. As for *how* to find the solution for this particular problem, I think I would first try to "mask" all the bits except for one, and see if that one bit is a `1` or a `0`. And then do the same thing for the rest. Although, I would definitely prefer the simpler approach that @Miller mentioned. – NigoroJr Apr 23 '14 at 05:08
  • Note that division by a power of two is *not* equivalent to right-shifting in Perl unless `use integer` is in effect. For example, the expression `64 / 128` yields `0.5`. In the context of this question, it doesn't make a difference, though. – nwellnhof Apr 23 '14 at 12:25
1

The numbers 1,2,4,8 are all powers of 2. So the bitwise & of any number with them will only have 2 possible values, The power of 2 or 0.

Then taking the result and dividing it by itself will give a result of either 0 or 1.

By the way, the easier method to convert a number to binary is to use sprintf:

sprintf "%b", 145;

Outputs:

10010001
Miller
  • 34,962
  • 4
  • 39
  • 60