"be consistent" PerlMonks

### Understanding Unpack on Decimal Value

by arblargan (Acolyte)
 on Nov 01, 2018 at 20:41 UTC Need Help??

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

Howdy Monks! I've got a question about what goes on behind the scenes when the function unpack is called. I'm trying to understand the results of a certain function for a script I inherited, but I can't figure out how the result is being calculated by Perl. See below for a snippet of the function.

```my \$input = 0x916CD; #595661
my \$unpacked = unpack "V", \$input;
print(\$unpacked);
>>909457717 (0x36353935)

I just can't seem to figure out, by hand, how Perl is unpacking the decimal value into that number. Can someone shed some light on what goes on behind the scenes in the unpack function that might be able to help me understand? Thanks!

Replies are listed 'Best First'.
Re: Understanding Unpack on Decimal Value
by choroba (Cardinal) on Nov 01, 2018 at 21:05 UTC
First, check pack:

> V An unsigned long (32-bit) in "VAX" (little-endian) order.

Have you noticed the pattern?

```         bytes              chars
36353935 ----> 36 35 39 35  ---->  6 5 9 5
| | | |
first 4 digits      reverse | | | |
595661 -------------> 5956 ------> 6 5 9 5

It works for any input greater or equal to 1000:

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

use Test::More;

sub what {
my (\$input) = @_;
my \$unpacked = unpack "V", \$input;
my \$result = join "", map chr hex, sprintf("%x\n", \$unpacked) =~ /
+(..)/g;
is \$result, reverse substr \$input, 0, 4;
}

what(\$_) for 1000 .. 2000,
2e4, 3e5, 4e6, 5e7, 6e8, 7e9, 8e10, 9e11, 2 ** 64 - 3;

done_testing();

Update: For numbers fitting into integer, you can also use

```reverse(\$input) % 10_000

```(\$q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord
}map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+\$1,++print+eval\$q,q,a,

ASCII!! That didn't even occur to me as this portion of the function is entirely numeric. I suspect that the way this was implemented in the original script was incorrectly understood. Thank you for the clarification. One additional question, if I could...

Since it returns only a portion of the result, I attempted to modify the snippet a little bit, but it still produced the same result. See below.

```my \$input = 0x916CD; #595661
my @unpacked = unpack "VV", \$input;
print(join ", ", @unpacked);
>>909457717 #0x36353935

```Dec: 825_636_405, 14_645
Hex: 0x31363635, 0x3935

Could you help me understand why this doesn't unpack into the array like I thought it would? Thanks for the help!

You need a number greater than 9_999_999 to get more than one element back:
```for my \$input (9_999_990 .. 10_000_010) {
my @unpacked = unpack 'VV', \$input;
say scalar @unpacked, " \$input";
}
```(\$q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord
}map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+\$1,++print+eval\$q,q,a,
Re: Understanding Unpack on Decimal Value
by BillKSmith (Monsignor) on Nov 03, 2018 at 13:34 UTC
Much of the strangeness that choroba describes has nothing to do with unpack. Unpack requires a string input. Your input is a number. When perl needs a number in the form of a string, it converts it much the way print would. Your "V" tells unpack to process the first four characters of that string. I suspect that your original programmer meant to use pack rather than unpack.
Bill

Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1225073]
Approved by marto
Front-paged by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (4)
As of 2023-06-08 08:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
How often do you go to conferences?

Results (29 votes). Check out past polls.

Notices?