Converting 4 bytes to a float

Discussion in 'Perl Misc' started by Larry.Martell@gmail.com, May 9, 2007.

  1. Guest

    I have a situation where I have to read in 4 values from a text file,
    then convert that into a float that I can use for arithmetic.

    For example, the file contains "85,170,174,214" - I read this in, and
    split it into an array, @d

    In C, I would do something akin to this:

    union convert_float32 {
    float f; // float view
    unsigned int i; // uint32 view
    } c;
    unsigned char i[4];
    char *q;

    for (int j=0; j<4; j++) i[j] = (unsigned char)strtoul(d[j], &q, 10);
    c.i = ((unsigned int)i[0] << 24) | ((unsigned int)i[1] << 16) |
    ((unsigned int)i[2] << 8) | (unsigned int)i[3];

    and c.f would have the value I want (in this example
    23458486419456.000000)

    Is there some way I can achieve the result with perl?

    TIA!
    -larry




    How can I do a similar conversion in perl?
     
    , May 9, 2007
    #1
    1. Advertising

  2. On May 9, 1:35 am, "" <>
    wrote:
    > I have a situation where I have to read in 4 values from a text file,
    > then convert that into a float that I can use for arithmetic.
    >
    > For example, the file contains "85,170,174,214" - I read this in, and
    > split it into an array, @d
    >
    > In C, I would do something akin to this:
    >
    > union convert_float32 {
    > float f; // float view
    > unsigned int i; // uint32 view} c;
    >
    > unsigned char i[4];
    > char *q;
    >
    > for (int j=0; j<4; j++) i[j] = (unsigned char)strtoul(d[j], &q, 10);
    > c.i = ((unsigned int)i[0] << 24) | ((unsigned int)i[1] << 16) |
    > ((unsigned int)i[2] << 8) | (unsigned int)i[3];
    >
    > and c.f would have the value I want (in this example
    > 23458486419456.000000)
    >
    > Is there some way I can achieve the result with perl?
    >
    > TIA!
    > -larry
    >
    > How can I do a similar conversion in perl?
     
    Brian McCauley, May 9, 2007
    #2
    1. Advertising

  3. On May 9, 1:35 am, "" <>
    wrote:
    > I have a situation where I have to read in 4 values from a text file,
    > then convert that into a float that I can use for arithmetic.
    >
    > For example, the file contains "85,170,174,214" - I read this in, and
    > split it into an array, @d
    >
    > In C, I would do something akin to this:
    >
    > union convert_float32 {
    > float f; // float view
    > unsigned int i; // uint32 view
    >} c;



    > unsigned char i[4];
    > char *q;
    >
    > for (int j=0; j<4; j++) i[j] = (unsigned char)strtoul(d[j], &q, 10);
    > c.i = ((unsigned int)i[0] << 24) | ((unsigned int)i[1] << 16) |
    > ((unsigned int)i[2] << 8) | (unsigned int)i[3];
    >
    > and c.f would have the value I want (in this example
    > 23458486419456.000000)


    Actually it would make more sense to get rid of the intermediate step.

    union convert_float32 {
    float f; // float view
    unsigned char i[4]; // 4 byte view
    } c;

    > Is there some way I can achieve the result with perl?


    You are looking for the pack() and unpack() functions.
     
    Brian McCauley, May 9, 2007
    #3
  4. Dr.Ruud Guest

    schreef:

    > I have a situation where I have to read in 4 values from a text file,
    > then convert that into a float that I can use for arithmetic.


    First convert the values into a buffer of 4 bytes. Then use unpack().
    See perldoc -f unpack.


    $ perl -wle 'print length pack "f", 1.23'
    4

    $ perl -wle 'print ord for split "", pack "f", 1.23'
    164
    112
    157
    63

    $ perl -wle 'print unpack "f", chr(164).chr(112).chr(157).chr(63)'
    1.23000001907349

    --
    Affijn, Ruud

    "Gewoon is een tijger."
     
    Dr.Ruud, May 9, 2007
    #4
  5. Guest

    On May 9, 12:37 am, Brian McCauley <> wrote:
    > On May 9, 1:35 am, "" <>
    > wrote:
    >
    >
    >
    > > I have a situation where I have to read in 4 values from a text file,
    > > then convert that into a float that I can use for arithmetic.

    >
    > > For example, the file contains "85,170,174,214" - I read this in, and
    > > split it into an array, @d

    >
    > > In C, I would do something akin to this:

    >
    > > union convert_float32 {
    > > float f; // float view
    > > unsigned int i; // uint32 view
    > >} c;
    > > unsigned char i[4];
    > > char *q;

    >
    > > for (int j=0; j<4; j++) i[j] = (unsigned char)strtoul(d[j], &q, 10);
    > > c.i = ((unsigned int)i[0] << 24) | ((unsigned int)i[1] << 16) |
    > > ((unsigned int)i[2] << 8) | (unsigned int)i[3];

    >
    > > and c.f would have the value I want (in this example
    > > 23458486419456.000000)

    >
    > Actually it would make more sense to get rid of the intermediate step.
    >
    > union convert_float32 {
    > float f; // float view
    > unsigned char i[4]; // 4 byte view
    >
    > } c;
    > > Is there some way I can achieve the result with perl?

    >
    > You are looking for the pack() and unpack() functions.


    Thanks - I got this to work using unpack().

    -larry
     
    , May 9, 2007
    #5
  6. Guest

    On May 9, 12:51 am, "Dr.Ruud" <> wrote:
    > schreef:
    >
    > > I have a situation where I have to read in 4 values from a text file,
    > > then convert that into a float that I can use for arithmetic.

    >
    > First convert the values into a buffer of 4 bytes. Then use unpack().
    > See perldoc -f unpack.
    >
    > $ perl -wle 'print length pack "f", 1.23'
    > 4
    >
    > $ perl -wle 'print ord for split "", pack "f", 1.23'
    > 164
    > 112
    > 157
    > 63
    >
    > $ perl -wle 'print unpack "f", chr(164).chr(112).chr(157).chr(63)'
    > 1.23000001907349


    Thanks much - this is exactly what I was looking for. I had read about
    pack and unpack,
    but I had their functionality reversed. Your post clarified things for
    me. I had to put the
    bytes in in reverse order (to deal with the little-endiness of my
    machine), but once I did
    that I got the correct result:

    $ perl -wle 'print unpack "f",chr(214).chr(174).chr(170).chr(85)'
    23458486419456

    Thanks again!
    -larry
     
    , May 9, 2007
    #6
  7. On 2007-05-09 06:37, Brian McCauley <> wrote:
    > On May 9, 1:35 am, "" <>
    > wrote:
    >> In C, I would do something akin to this:
    >>
    >> union convert_float32 {
    >> float f; // float view
    >> unsigned int i; // uint32 view
    >>} c;

    >
    >
    >> unsigned char i[4];
    >> char *q;
    >>
    >> for (int j=0; j<4; j++) i[j] = (unsigned char)strtoul(d[j], &q, 10);
    >> c.i = ((unsigned int)i[0] << 24) | ((unsigned int)i[1] << 16) |
    >> ((unsigned int)i[2] << 8) | (unsigned int)i[3];
    >>
    >> and c.f would have the value I want (in this example
    >> 23458486419456.000000)

    >
    > Actually it would make more sense to get rid of the intermediate step.
    >
    > union convert_float32 {
    > float f; // float view
    > unsigned char i[4]; // 4 byte view
    > } c;


    I don't think so. You are introducing an endian dependency which the
    OP's code didn't have.


    >> Is there some way I can achieve the result with perl?

    >
    > You are looking for the pack() and unpack() functions.


    Unfortunately pack does't have a format for "single precision IEEE-754
    floating point number in network byte order", so - as the OP already
    found out - you either need to know the endianness of your platform, or
    you need to convert from network (big endian) byte order to native byte
    order first:

    $fp_value = unpack('f', pack('L', unpack('N', $bytes)));

    hp

    --
    _ | Peter J. Holzer | I know I'd be respectful of a pirate
    |_|_) | Sysadmin WSR | with an emu on his shoulder.
    | | | |
    __/ | http://www.hjp.at/ | -- Sam in "Freefall"
     
    Peter J. Holzer, May 13, 2007
    #7
    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. Andy
    Replies:
    7
    Views:
    6,265
    Roedy Green
    May 10, 2004
  2. bd
    Replies:
    0
    Views:
    632
  3. mathieu
    Replies:
    9
    Views:
    741
    James Kanze
    Sep 15, 2007
  4. Replies:
    6
    Views:
    608
    Logan Shaw
    Mar 23, 2008
  5. Carsten Fuchs
    Replies:
    45
    Views:
    1,553
    James Kanze
    Oct 8, 2009
Loading...

Share This Page