http://qs1969.pair.com?node_id=1225073

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