In <dhn80f$4vn$>
(Anno Siegel) writes:
>kj <> wrote in comp.lang.perl.misc:
>I'll show how to generate a string (not an array) of zeroes and ones.
>You need two steps. First use the "f" template (single-precision float)
>to get the four bytes that make up a 32-bit float into a string. If
>the number is in $_:
> my $str = pack 'f', $_;
>Next, unpack the result as a bit string, using the "b" template
> my $bits = unpack 'b32', $str;
>Run it for a few examples
> printf "%.3f -> %s\n", $_, unpack 'b32', pack 'f', $_ for
> 1/8, 1/4, 1/2, 1, 2, 4, 8;
>and see if you can make heads or tails of the output. The bytes may not
>be in the expected order. On my machine, I get:
>0.125 -> 01111100000000000000000000000000
>0.250 -> 01111100000000010000000000000000
>0.500 -> 11111100000000000000000000000000
>1.000 -> 11111100000000010000000000000000
>2.000 -> 00000010000000000000000000000000
>4.000 -> 00000010000000010000000000000000
>8.000 -> 10000010000000000000000000000000
>If you want an array, either split the result in single characters, or
>use
> map vec( $str, $_, 1), 0 .. 31
>instead of unpacking with "b".
Thank you very much. That was very helpful.
BTW, I was surprised to discover that the vec alternative is about
2.5x faster than unpack+split:
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.1. 1.1.1.1.1.0.0
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.1. 1.1.1.1.1.0.0
Rate unp vec
unp 26305/s -- -61%
vec 67622/s 157% --
I give the code below.
kj
use Benchmark 'cmpthese';
$::f = pack 'f', 1;
my $subs = {vec => 'map vec($::f, $_, 1), 0..31',
unp => 'split "", unpack "b32", $::f'};
# check that both work and produce the same result
{
local ($\, $,) = ("\n", '.');
print eval('sub {'.$subs->{ $_ }.'}')->(), "\n" for qw(vec unp);
}
# benchmark
cmpthese -1, $subs;
__END__
--
NOTE: In my address everything before the first period is backwards;
and the last period, and everything after it, should be discarded.