Need help with pack

Discussion in 'Perl Misc' started by kj, Oct 2, 2005.

  1. kj

    kj Guest

    I want to write the function to_bits that takes a floating point
    number as argument and returns an array of 32 ones or zeroes,
    corresponding to the bits of the input argument.

    I have been staring at the docs for pack and unpack for a while
    now trying to figure out how to use them to do this and I am as
    clueless about it as I was when I first started. Also, perlpacktut
    was no help either [1].

    If someone could please tell me how to generate an array of one's
    and zeros corresponding to the bits in a floating point number I'd
    be very grateful.

    kj

    [1] Lest I appear very lazy or very stupid, I should point out that
    I generally have *no problem* understanding the documentation for
    Perl built-in functions. pack is a very exceptional case. It is
    the only Perl function that I consider mysterious in the least.
    I wish I could convey my bewilderment upon reading the docs for
    pack. From the very first sentences it is as if I were reading
    some English-like code in which all words mean something different
    from what I think they should mean. As I said, the tutorial is no
    help, because ultimately the tutorial just gives cookbook recipes
    which I can follow, but I have no idea what I'm doing. If what I
    need to do is not described in one of the recipes, then *I have no
    idea* of how to devise my own recipe.
    --
    NOTE: In my address everything before the first period is backwards;
    and the last period, and everything after it, should be discarded.
     
    kj, Oct 2, 2005
    #1
    1. Advertising

  2. kj wrote:
    > I want to write the function to_bits that takes a floating point
    > number as argument and returns an array of 32 ones or zeroes,
    > corresponding to the bits of the input argument.
    >
    > I have been staring at the docs for pack and unpack for a while
    > now trying to figure out how to use them to do this and I am as
    > clueless about it as I was when I first started. Also, perlpacktut
    > was no help either [1].
    >
    > If someone could please tell me how to generate an array of one's
    > and zeros corresponding to the bits in a floating point number I'd
    > be very grateful.



    $ perl -le' print for unpack q/a/ x 32, unpack q/b*/, pack q/f/, 5.678 '
    1
    0
    1
    1
    0
    1
    0
    0
    0
    1
    0
    0
    1
    1
    0
    1
    1
    0
    1
    0
    1
    1
    0
    1
    0
    0
    0
    0
    0
    0
    1
    0



    John
    --
    use Perl;
    program
    fulfillment
     
    John W. Krahn, Oct 2, 2005
    #2
    1. Advertising

  3. kj

    tlm Guest


    >I want to write the function to_bits that takes a floating point
    >number as argument and returns an array of 32 ones or zeroes,
    >corresponding to the bits of the input argument.


    How about this (untested):

    sub to_bits {
    my $f = pack 'f', shift;
    return reverse map vec( $f, $_, 1 ), 0 .. 31;
    }

    HTH,

    tlm
    --
    NOTE: In my address everything before the first period is backwards;
    and the last period, and everything after it, should be discarded.
     
    tlm, Oct 2, 2005
    #3
  4. kj <> wrote in news:dhn4dh$bqd$:

    > I want to write the function to_bits that takes a floating point
    > number as argument and returns an array of 32 ones or zeroes,
    > corresponding to the bits of the input argument.
    >
    > I have been staring at the docs for pack and unpack for a while
    > now trying to figure out how to use them to do this and I am as
    > clueless about it as I was when I first started. Also, perlpacktut
    > was no help either [1].
    >
    > If someone could please tell me how to generate an array of one's
    > and zeros corresponding to the bits in a floating point number I'd
    > be very grateful.


    #!/usr/bin/perl

    use strict;
    use warnings;

    print unpack 'b*', pack 'f', 3.45;


    Sinan

    --
    A. Sinan Unur <>
    (reverse each component and remove .invalid for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
     
    A. Sinan Unur, Oct 2, 2005
    #4
  5. kj

    Anno Siegel Guest

    kj <> wrote in comp.lang.perl.misc:
    >
    >
    >
    > I want to write the function to_bits that takes a floating point
    > number as argument and returns an array of 32 ones or zeroes,
    > corresponding to the bits of the input argument.
    >
    > I have been staring at the docs for pack and unpack for a while
    > now trying to figure out how to use them to do this and I am as
    > clueless about it as I was when I first started. Also, perlpacktut
    > was no help either [1].
    >
    > If someone could please tell me how to generate an array of one's
    > and zeros corresponding to the bits in a floating point number I'd
    > be very grateful.


    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".

    Anno
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
     
    Anno Siegel, Oct 2, 2005
    #5
  6. kj

    kj Guest

    In <dhn80f$4vn$-Berlin.DE> -berlin.de (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.
     
    kj, Oct 2, 2005
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. PL

    Help Service Pack 4 Problem

    PL, Jul 2, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    374
  2. George Davis
    Replies:
    1
    Views:
    1,078
    WebcastMaker
    Aug 29, 2004
  3. Tim Jones
    Replies:
    0
    Views:
    405
    Tim Jones
    Jan 31, 2004
  4. sarah Fernandes
    Replies:
    0
    Views:
    293
    sarah Fernandes
    Mar 4, 2011
  5. Alexander Farber

    pack 'C3U*' not same as pack 'C3(xC)*'

    Alexander Farber, Jun 23, 2005, in forum: Perl Misc
    Replies:
    2
    Views:
    170
    Ilmari Karonen
    Jun 23, 2005
Loading...

Share This Page