0

I have a binary no say and I have a value in variable say value = 4. I want to right shift the binary no by no of bits stored in "value" variable and then want to store the shifted bits in a variable and also want to save binary no obtained after right shift in another variable

Example:

binary_number = 110000001
value =4 
then shifting no of bits in "value" to right (11000001 >> value)

Now I want to finally have two variables one containing the binary no after shift and one variable with shifted bits.

For above example the solution that I want is

right_shifted_binary = 11000
bits_shifted = 0001

I can not find a proper documentation for the problem as most of the problem are telling about arithmetic right shift.

Stefan Becker
  • 5,695
  • 9
  • 20
  • 30
rikki
  • 431
  • 1
  • 8
  • 18
  • Can you give a bit of context? This sounds like an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Typically, doing the shift on decimal numbers would make more sense. However, if you are sure that this is what you want to do, then use [`substr`](https://perldoc.perl.org/functions/substr.html) (what you call a "binary number" is seen by Perl as a string, not a number). – Dada Mar 26 '19 at 10:12
  • I assume that `$binary_number` is an integer scalar and not a string? If it would be a string you could simply use `substr()` to extract the right bits. – Stefan Becker Mar 26 '19 at 11:06
  • @StefanBecker Given OP's [previous question](https://stackoverflow.com/questions/55351735/appending-0-before-binary-number-based-on-a-value-in-a-variable), I suppose that `$binary_number` is a string, but I might be wrong. (and that information should definitely be in the question: OP, please, clarify that) – Dada Mar 26 '19 at 12:34

1 Answers1

1

Generate a bit mask based on $value and use the AND (&) operator:

#!/usr/bin/perl
use warnings;
use strict;

my $binary = 0b110000001;
my $value  = 4;

# create mask with $value left-most bits 1
my $mask = ~(~0 << $value);

print "INPUT:     ", unpack("B*", pack("N", $binary)), " ($binary)\n";

# right shift by $value bits
my $right_shifted_binary = $binary >> $value;
print "RIGHT:     ", unpack("B*", pack("N", $right_shifted_binary)), " ($right_shifted_binary)\n";

# extract "remainder" of shift using mask
my $bits_shifted = $binary & $mask;
print "REMAINDER: ", unpack("B*", pack("N", $bits_shifted)), " ($bits_shifted)\n";

exit 0;

Test run:

$ perl dummy.pl
INPUT:     00000000000000000000000110000001 (385)
RIGHT:     00000000000000000000000000011000 (24)
REMAINDER: 00000000000000000000000000000001 (1)

# Proof
$ echo "24 * 16 + 1" | bc
385

If the binary number is given as string you can convert it to an integer first:

my $binary_string = "110000001";
my $binary = unpack("N", pack("B32", substr("0" x 32 . $binary_string, -32)));

But if it is already a string then the solution would be much simpler:

#!/usr/bin/perl
use warnings;
use strict;

my $binary_string = "110000001";
my $value  = 4;

print "INPUT:     $binary_string\n";
print "RIGHT:     ", substr($binary_string, 0, -$value), "\n";
print "REMAINDER: ", substr($binary_string, -$value),    "\n";

exit 0:
$ perl dummy.pl
INPUT:     110000001
RIGHT:     11000
REMAINDER: 0001
Stefan Becker
  • 5,695
  • 9
  • 20
  • 30