Syntactic Confectionery Delight PerlMonks

### Re: 3-byte representation

by ikegami (Pope)
 on Oct 12, 2011 at 17:50 UTC ( #931057=note: print w/replies, xml ) Need Help??

If you want big-endian byte order:

```pack:   \$s = substr(pack('l>', \$n), 1);
unpack: \$n = unpack('l>', "\$s\0")/256;

If you want little-endian byte order:

```pack:   \$s = substr(pack('l<', \$n), 0, 3);
unpack: \$n = unpack('l<', "\0\$s")/256;

PS — Going from 3 to 4 increases the space needed by 33%, not 25%.

Update: Slightly simpler solutions.
Update: The /256 got dropped when I posted my solution. Fixed.

Replies are listed 'Best First'.
Re^2: 3-byte representation
by BrowserUk (Pope) on Oct 12, 2011 at 18:32 UTC

Hm?

Big-endian:

```sub pack24{ substr( pack('l>', \$_[0]), 1) };;
sub unpack24{ unpack('l>', "\$_[0]\0") };;

print "\$_: ", unpack24( pack24( \$_ ) )
for ( -8388608, -8388607, -2, -1, 0, 1, 2, 8388606, 8388607 );;
-8388608:  -2147483648
-8388607:  -2147483392
-2:  -512
-1:  -256
0:  0
1:  256
2:  512
8388606:  2147483136
8388607:  2147483392

Little-endian:

```sub pack24{ substr( pack('l<', \$_[0]), 1) };;
sub unpack24{ unpack('l<', "\$_[0]\0") };;

print "\$_: ", unpack24( pack24( \$_ ) )
for ( -8388608, -8388607, -2, -1, 0, 1, 2, 8388606, 8388607 );;
-8388608:  16744448
-8388607:  16744448
-2:  16777215
-1:  16777215
0:  0
1:  0
2:  0
8388606:  32767
8388607:  32767

Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

Thanks, a "/256" got accidentally dropped when I posted my code. Fixed.

Re^2: 3-byte representation
by BrowserUk (Pope) on Oct 12, 2011 at 19:10 UTC
I tested my solutions before posting them.

Really? Really, really? Hm?

```#! perl -slw
use strict;

sub   pack24be{ substr( pack('l>', \$_[0]), 1)      }
sub unpack24be{ unpack('l>', "\$_[0]\0") >> 8       }

sub   pack24le{ substr( pack('l<', \$_[0] ), 0, 3); }
sub unpack24le{ unpack( 'l<', "\0\$_[0]" ) >> 8     }

print( "be: \$_: ", unpack24be( pack24be( \$_ ) ) ),
print( "le: \$_: ", unpack24le( pack24le( \$_ ) ) )
for ( -8388608, -8388607, -2, -1, 0, 1, 2, 8388606, 8388607 )

__END__
C:\test>junk101 (version 2 )
be: -8388608: -2147483648
le: -8388608: -2147483648
be: -8388607: -2147483392
le: -8388607: -2147483392
be: -2: -512
le: -2: -512
be: -1: -256
le: -1: -256
be: 0: 0
le: 0: 0
be: 1: 256
le: 1: 256
be: 2: 512
le: 2: 512
be: 8388606: 2147483136
le: 8388606: 2147483136
be: 8388607: 2147483392
le: 8388607: 2147483392

C:\test>junk101 (version 3)
be: -8388608: 72057594029539328
le: -8388608: 72057594029539328
be: -8388607: 72057594029539329
le: -8388607: 72057594029539329
be: -2: 72057594037927934
le: -2: 72057594037927934
be: -1: 72057594037927935
le: -1: 72057594037927935
be: 0: 0
le: 0: 0
be: 1: 1
le: 1: 1
be: 2: 2
le: 2: 2
be: 8388606: 8388606
le: 8388606: 8388606
be: 8388607: 8388607
le: 8388607: 8388607

Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
Re^2: 3-byte representation
by BrowserUk (Pope) on Oct 12, 2011 at 19:12 UTC
Update: The >> 8 got dropped when I posted my solution. Fixed.

Silently becomes

Update: The /256 got dropped when I posted my solution. Fixed.

Hm. "Got dropped" huh!

Thank you for all your gentle answers, but if I run this:
```#!/usr/bin/perl
print "Content-type: text/html\n\n";
srand();
\$fil="ch";
open(OUT, '>>'.\$fil);
for(\$i=1;\$i<10001;\$i++){
\$j=int(rand(20000))+440000;
\$k=substr(pack('l>',\$j),1);
print OUT \$k;
}
close(OUT);
print "DONE !";
it produces one file with a variable length, but always greater than 30000 characters (for exemple 30045) ! So I suppose something is wrong in the pack line coding...

Add binmode OUT after the open.

Also,

1. you should be using a mode of '>' not '>>', unless your intention is to append to an existing file.
2. for(\$i=1;\$i<10001;\$i++){ is more easily and clearly written as for my \$i ( 1 .. 10000 ) {
3. int(rand(20000))+440000 produces always positive integer.

If you don't need signed integers, your question would have been much simpler to answer.

4. \$k=substr(pack('l>',\$j),1); print OUT \$k;

Packing and writing one value at a time is hugely expensive compared to packing all 10000 values in a single pass and then writing them once.

5. For goodness sake, use a little horizontal whitespace.

Don't you find this infinitely more readable?

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

print "Content-type: text/html\n\n";

srand();

my \$fil = "ch";
open( OUT, '>', \$fil ) or die \$!;
binmode OUT;

for my \$i ( 1  .. 10_000 ) {
my \$j = int( rand( 20_000 ) ) + 440_000;
my \$k = substr( pack( 'l>', \$j ), 1 );
print OUT \$k;
}

close( OUT );
print "DONE !";

Remember that your source code is the equivalent of the professional chef's plated up meal.

His presentation is what makes the difference between a paid for cover and a decent home cooked meal. It is both his edge and his profit margin.

Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
It was /256. Just misremembered cause I changed comps in the middle.

Create A New User
Node Status?
node history
Node Type: note [id://931057]
help
Chatterbox?
NodeReaper edits tomorrow's obituaries

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (9)
As of 2017-08-16 14:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
Who is your favorite scientist and why?

Results (266 votes). Check out past polls.

Notices?