Perl - convert hexadecimal to binary and use it as string
Asked Answered
M

4

5

I am new to Perl and I have difficulties using the different types.

I am trying to get an hexadecimal register, transform it to binary, use it a string and get substrings from the binary string.

I have done a few searches and what I tried is :

my $hex = 0xFA1F;
print "$hex\n";

result was "64031" . First surprise : can't I print the hex value in Perl and not just the decimal value ?

$hex = hex($hex);
print "$hex\n";

Result was 409649. Second surprise : I would expect the result to be also 64031 since "hex" converts hexadecimal to decimal.

my $bin = printf("%b", $hex);

It prints the binary value. Is there a way to transform the hex to bin without printing it ?

Thanks, SLP

Melvinmelvina answered 7/3, 2019 at 8:13 Comment(2)
Try adding quotes around the hex constant: my $hex ='0xFA1F'. If not it will be converted to the number 64031. Later, when you do hex(64031), 64031 is interpreted as the hexadecimal string 0x64031Floria
Thanks ! very simple indeed... it works for meMelvinmelvina
P
4

Decimal, binary, and hexadecimal are all text representations of a number (i.e. ways of writing a number). Computers can't deal with these as numbers.

my $num = 0xFA1F; stores the specified number (sixty-four thousand and thirty-one) into $num. It's stored in a format the hardware understands, but that's not very important. What's important is that it's stored as a number, not text.

When print is asked to print a number, it prints it out in decimal (or scientific notation if large/small enough). It has no idea how the number of created (from a hex constant? from addition? etc), so it can't determine how to output the number based on that.

To print an number as hex, you can use

my $hex = 'FA1F';   # $hex contains the hex representation of the number.
print $hex;         # Prints the hex representation of the number.

or

my $num = 0xFA1F;   # $num contains the number.
printf "%X", $num;  # Prints the hex representation of the number.
Pandich answered 7/3, 2019 at 9:12 Comment(1)
As a side note, Perl can deal with the decimal representation of a number as if it was a number. If a string is about to be used in a numerical operation, Perl will first convert the string from decimal to a number. This isn't relevant to the question.Pandich
A
3

You are assigning a integer value using hexadecimal format. print by default prints numbers in decimal format, so you are getting 64031.

You can verify this using the printf() by giving different formats.

$ perl -e ' my $num = 0xFA1F; printf("%d %X %b\n", ($num) x 3 ) '
64031 FA1F 1111101000011111

$ perl -e ' my $num = 64031; printf("%d %X %b\n", ($num) x 3 ) '
64031 FA1F 1111101000011111

$ perl -e ' my $num = 0b1111101000011111; printf("%d %X %b\n", ($num) x 3 ) '
64031 FA1F 1111101000011111

$

To get the binary format of 0xFA1F in string, you can use sprintf()

$ perl -e ' my $hex = 0xFA1F; my $bin=sprintf("%b",$hex) ; print "$bin\n" '
1111101000011111

$
Auscultation answered 7/3, 2019 at 13:17 Comment(0)
M
2

lets take each bit of confusion in order

my $hex = 0xFA1F;

This stores a hex constant in $hex, but Perl doesn't have a hex data type so although you can write hex constants, and binary and octal constants for that matter, Perl converts them all to decimal. Note that there is a big difference between

my $hex = 0xFA1F;

and

my $hex = '0xFA1F';

The first stores a number into $hex, which when you print it out you get a decimal number, the second stores a string which when printed out will give 0xFAF1 but can be passed to the hex() function to be converted to decimal.

$hex = hex($hex);

The hex function converts a string as if it was a hex number and returns the decimal value and, as up to this point, $hex has only ever been used as a number Perl will first stringify $hex then pass the string to the hex() function to convert that value from hex to decimal.

So to the solution. You are almost there with printf(),there is a function called sprintf() which takes the same parameters as printf() but instead of printing the formatted value returns it as a string. So what you need is.

my $hex = 0xFA1F;
my $bin = sprintf("%b", $hex);
print $bin;

Technical note: Yes I know that Perl stores all its numbers internally as binary, but lets not go there for this answer, OK?

Mara answered 7/3, 2019 at 8:44 Comment(3)
Re "Perl converts them all to decimal", No. Perl converts them to a format the computer understands (2's complement). Conversion to decimal (a text representation of a number) is done by print.Pandich
@Pandich See technical note at the bottom of the answer, I didn't want to confuse the questioner.Mara
I'd say a completely wrong explanation is more likely to confuse than anything else.Pandich
A
2

If you're ok with using a distribution, I wrote Bit::Manip to make my prototyping a bit easier when dealing with registers (There's also a Pure Perl version available if you have problems compiling the XS code).

Not only can it fetch out bits from a number, it can toggle, clear, set etc:

use warnings;
use strict;

use Bit::Manip qw(:all);

my $register = 0xFA1F;

# fetch the bits from register using msb, lsb

my $msbyte = bit_get($register, 15, 8);

print "value: $msbyte\n";

print "bin: " . bit_bin($msbyte) . "\n";

# or simply:
# printf "bin: %b\n", $msbyte;

Output:

value: 250
bin: 11111010

Here's a blog post I wrote that shows how to use some of the software's functionality with an example datasheet register.

Adlar answered 7/3, 2019 at 15:51 Comment(3)
this seams great, unforntunately I won't be able to download the library on my computer. Thank you for the answer thoughMelvinmelvina
@Melvinmelvina But you can download it! The link "Pure Perl" version is a single file, which seems to have no dependencies (doesn't itself use any special libraries), and which can directly be used in a Perl program. So you can literally download that file and put it wherever you keep your own modules. And that's that, use it. You can also see the module code (less than 200 lines!), and use that as you see it fit! I'm certain that the author won't mind :)Earthiness
@Earthiness Nope, I certainly don't mind at all! It's the reason I publish all my code with the Perl license :)Adlar

© 2022 - 2024 — McMap. All rights reserved.