Hex to floating point

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • DvGrimm

    Hex to floating point

    Any help would be very, very much appreciated...
    I've been searching the net (google) for 4 days now trying to find a php
    function to convert hex to floating point.
    I'm converting old transactional data files to mysql and I'm stumped trying
    to convert the currency data bytes.

    For example: I'm looking for a php function to convert (40 3E 51 EB 85 1E
    B8 52) hex to ($30.32) foating (double precision 64 bits)

    I'm not sure if this convertion is OS dependent??
    I'm using php and apache on WinXP (my laptop). But will be migrating to
    code a Linux and apache server when complete.

    David
    =============== =
    The following code was posted by Chung Leong. This works very well from
    floating point to hex, however, I require a php function to convert hex to
    double precision floating point.
    =============== =============== ===
    Reverse engineering a file format is not easy. Basically, there's two ways
    the records could be stored: fixed-size or variable size. With a hex editor,
    try to figure out the size of different records. Variable size records
    usually store its length at the first byte or word.

    It looks like some of the data is stored as floating points. Here's a couple
    function that show the binary representation of single and double precision
    floats:

    function ieee_double($f) {
    $f = (double) $f;
    $b = pack("d", $f);
    $hex = "";
    for($i = 0; $i < strlen($b); $i++) {
    $c = ord($b{$i});
    $hex .= sprintf(" %02X", $c);
    } return $hex;
    }

    function ieee_float($f) {
    $f = (float) $f;
    $b = pack("f", $f);
    $hex = "";
    for($i = 0; $i < strlen($b); $i++) {
    $c = ord($b{$i});
    $hex .= sprintf(" %02X", $c);
    } return $hex;
    }



  • Pedro Graca

    #2
    Re: Hex to floating point

    DvGrimm wrote:[color=blue]
    > For example: I'm looking for a php function to convert (40 3E 51 EB 85 1E
    > B8 52) hex to ($30.32) foating (double precision 64 bits)
    >
    > I'm not sure if this convertion is OS dependent??[/color]

    Probably (definitely?) it is.
    [color=blue]
    > I'm using php and apache on WinXP (my laptop). But will be migrating to
    > code a Linux and apache server when complete.
    >
    > David[/color]
    [color=blue]
    >============== ==
    > The following code was posted by Chung Leong. This works very well from
    > floating point to hex, however, I require a php function to convert hex to
    > double precision floating point.
    >============== =============== ====[/color]

    I tool your example ("40 3E 51 EB 85 1E B8 52") as a string
    [color=blue]
    > function ieee_double($f) {
    > $f = (double) $f;
    > $b = pack("d", $f);
    > $hex = "";
    > for($i = 0; $i < strlen($b); $i++) {
    > $c = ord($b{$i});
    > $hex .= sprintf(" %02X", $c);
    > } return $hex;
    > }[/color]


    First you have to reverse the for() loop;
    then the pack() call.

    I did it like this


    <?php
    function hexreverse($x) {
    $r = '';
    $y = explode(' ', $x);
    foreach ($y as $z) {
    $r = $z . ' ' . $r;
    }
    return substr($r, 0, -1);
    }

    function hexify($x) {
    static $v = array(
    '0'=>0, '1'=>1, '2'=>2, '3'=>3,
    '4'=>4, '5'=>5, '6'=>6, '7'=>7,
    '8'=>8, '9'=>9, 'A'=>10, 'B'=>11,
    'C'=>12, 'D'=>13, 'E'=>14, 'F'=>15,
    'a'=>10, 'b'=>11, 'c'=>12, 'd'=>13, 'e'=>14, 'f'=>15,
    );
    $r = '';
    $y = explode(' ', $x);
    foreach ($y as $z) {
    if (!ctype_xdigit( $z)) return false;
    $tmp = $v[$z{0}] * 16 + $v[$z{1}];
    $r .= chr($tmp);
    }
    return $r;
    }


    $x0 = "40 3E 51 EB 85 1E B8 52";
    $x1 = hexreverse($x0) ; /* I need this: OS = Linux */
    $x2 = hexify($x1); /* reverse the for() loop; */
    if ($x2 === false) die("Invalid input\n");
    $x3 = unpack("d", $x2); /* reverse the pack() call */
    $y = $x3[1];
    var_dump($y); /* dump() the final value. */
    ?>

    --
    Mail sent to my "From:" address is publicly readable at http://www.dodgeit.com/
    == ** ## !! !! ## ** ==
    TEXT-ONLY mail to the complete "Reply-To:" address ("My Name" <my@address>) may
    bypass the spam filter. I will answer all pertinent mails from a valid address.

    Comment

    • Brion Vibber

      #3
      Re: Hex to floating point

      DvGrimm wrote:[color=blue]
      > Any help would be very, very much appreciated...
      > I've been searching the net (google) for 4 days now trying to find a php
      > function to convert hex to floating point.[/color]

      The unpack function can do this, provided it's in the right format.
      [color=blue]
      > I'm converting old transactional data files to mysql and I'm stumped trying
      > to convert the currency data bytes.
      >
      > For example: I'm looking for a php function to convert (40 3E 51 EB 85 1E
      > B8 52) hex to ($30.32) foating (double precision 64 bits)
      >
      > I'm not sure if this convertion is OS dependent??[/color]

      It's unlikely to be OS-dependent, but it is certainly machine-dependent.
      A little-endian CPU (such as x86) will use the bytes in the opposite
      order from a big-endian CPU (such as SPARC or PowerPC). It looks like
      your data is in big-endian order, so on a PowerPC-based Macintosh this
      simple code works and prints out "30.32":

      function bin2double($bin ) {
      $unpacked = unpack("d", $bin);
      return $unpacked[1];
      }

      $x = "\x40\x3E\x51\x EB\x85\x1E\xB8\ x52";
      echo bin2double($x), "\n";

      But on an x86-based Linux PC it produces "3.07073382227E +90". A Windows
      PC will probably produce the same result.
      [color=blue]
      > I'm using php and apache on WinXP (my laptop). But will be migrating
      > to code a Linux and apache server when complete.[/color]

      See the online documentation for the 'unpack' function. There's a
      comment on that page with some code for swapping the byte order in the
      other direction, which you can probably adapt to your situation fairly
      easily. (Byte-swapping is the same operation in either direction, so you
      should just need to change the condition that triggers the swap.)



      -- brion vibber (brion @ pobox.com)

      Comment

      • Chung Leong

        #4
        Re: Hex to floating point

        Why write your own hex decoder when there's good old sscanf()? A more
        compact version:

        $s = "40 3E 51 EB 85 1E B8 52";
        $hex = sscanf($s, "%02x %02x %02x %02x %02x %02x %02x %02x");
        $hex = array_reverse($ hex);
        $bin = implode('', array_map('chr' , $hex));
        $array = unpack("dnum", $bin);
        echo $array['num'];

        "Pedro Graca" <hexkid@dodgeit .com> wrote in message
        news:slrncq51f6 .1de.hexkid@ID-203069.user.uni-berlin.de...[color=blue]
        > DvGrimm wrote:[color=green]
        > > For example: I'm looking for a php function to convert (40 3E 51 EB 85[/color][/color]
        1E[color=blue][color=green]
        > > B8 52) hex to ($30.32) foating (double precision 64 bits)
        > >
        > > I'm not sure if this convertion is OS dependent??[/color]
        >
        > Probably (definitely?) it is.
        >[color=green]
        > > I'm using php and apache on WinXP (my laptop). But will be migrating[/color][/color]
        to[color=blue][color=green]
        > > code a Linux and apache server when complete.
        > >
        > > David[/color]
        >[color=green]
        > >============== ==
        > > The following code was posted by Chung Leong. This works very well from
        > > floating point to hex, however, I require a php function to convert hex[/color][/color]
        to[color=blue][color=green]
        > > double precision floating point.
        > >============== =============== ====[/color]
        >
        > I tool your example ("40 3E 51 EB 85 1E B8 52") as a string
        >[color=green]
        > > function ieee_double($f) {
        > > $f = (double) $f;
        > > $b = pack("d", $f);
        > > $hex = "";
        > > for($i = 0; $i < strlen($b); $i++) {
        > > $c = ord($b{$i});
        > > $hex .= sprintf(" %02X", $c);
        > > } return $hex;
        > > }[/color]
        >
        >
        > First you have to reverse the for() loop;
        > then the pack() call.
        >
        > I did it like this
        >
        >
        > <?php
        > function hexreverse($x) {
        > $r = '';
        > $y = explode(' ', $x);
        > foreach ($y as $z) {
        > $r = $z . ' ' . $r;
        > }
        > return substr($r, 0, -1);
        > }
        >
        > function hexify($x) {
        > static $v = array(
        > '0'=>0, '1'=>1, '2'=>2, '3'=>3,
        > '4'=>4, '5'=>5, '6'=>6, '7'=>7,
        > '8'=>8, '9'=>9, 'A'=>10, 'B'=>11,
        > 'C'=>12, 'D'=>13, 'E'=>14, 'F'=>15,
        > 'a'=>10, 'b'=>11, 'c'=>12, 'd'=>13, 'e'=>14, 'f'=>15,
        > );
        > $r = '';
        > $y = explode(' ', $x);
        > foreach ($y as $z) {
        > if (!ctype_xdigit( $z)) return false;
        > $tmp = $v[$z{0}] * 16 + $v[$z{1}];
        > $r .= chr($tmp);
        > }
        > return $r;
        > }
        >
        >
        > $x0 = "40 3E 51 EB 85 1E B8 52";
        > $x1 = hexreverse($x0) ; /* I need this: OS = Linux */
        > $x2 = hexify($x1); /* reverse the for() loop; */
        > if ($x2 === false) die("Invalid input\n");
        > $x3 = unpack("d", $x2); /* reverse the pack() call */
        > $y = $x3[1];
        > var_dump($y); /* dump() the final value. */
        > ?>
        >
        > --
        > Mail sent to my "From:" address is publicly readable at[/color]
        http://www.dodgeit.com/[color=blue]
        > == ** ## !! !! ##[/color]
        ** ==[color=blue]
        > TEXT-ONLY mail to the complete "Reply-To:" address ("My Name"[/color]
        <my@address>) may[color=blue]
        > bypass the spam filter. I will answer all pertinent mails from a valid[/color]
        address.


        Comment

        • Pedro Graca

          #5
          Re: Hex to floating point

          Chung Leong wrote:[color=blue]
          > Why write your own hex decoder when there's good old sscanf()?[/color]
          <snip>

          Much better :-)
          Thanks Chung!

          --
          Mail sent to my "From:" address is publicly readable at http://www.dodgeit.com/
          == ** ## !! !! ## ** ==
          TEXT-ONLY mail to the complete "Reply-To:" address ("My Name" <my@address>) may
          bypass the spam filter. I will answer all pertinent mails from a valid address.

          Comment

          • DvGrimm

            #6
            Re: Hex to floating point

            Many thanks to all that contributated.. .
            I now have a solution that works.
            ....and I understand hex and its conversion way better.

            David

            "DvGrimm" <dgathomenow@ho tmail.com> wrote in message
            news:%Ttod.2004 65$9b.50368@edt nps84...[color=blue]
            > Any help would be very, very much appreciated...
            > I've been searching the net (google) for 4 days now trying to find a php
            > function to convert hex to floating point.
            > I'm converting old transactional data files to mysql and I'm stumped
            > trying to convert the currency data bytes.
            >
            > For example: I'm looking for a php function to convert (40 3E 51 EB 85 1E
            > B8 52) hex to ($30.32) foating (double precision 64 bits)
            >
            > I'm not sure if this convertion is OS dependent??
            > I'm using php and apache on WinXP (my laptop). But will be migrating to
            > code a Linux and apache server when complete.
            >
            > David
            > =============== =
            > The following code was posted by Chung Leong. This works very well from
            > floating point to hex, however, I require a php function to convert hex to
            > double precision floating point.
            > =============== =============== ===
            > Reverse engineering a file format is not easy. Basically, there's two ways
            > the records could be stored: fixed-size or variable size. With a hex
            > editor,
            > try to figure out the size of different records. Variable size records
            > usually store its length at the first byte or word.
            >
            > It looks like some of the data is stored as floating points. Here's a
            > couple
            > function that show the binary representation of single and double
            > precision
            > floats:
            >
            > function ieee_double($f) {
            > $f = (double) $f;
            > $b = pack("d", $f);
            > $hex = "";
            > for($i = 0; $i < strlen($b); $i++) {
            > $c = ord($b{$i});
            > $hex .= sprintf(" %02X", $c);
            > } return $hex;
            > }
            >
            > function ieee_float($f) {
            > $f = (float) $f;
            > $b = pack("f", $f);
            > $hex = "";
            > for($i = 0; $i < strlen($b); $i++) {
            > $c = ord($b{$i});
            > $hex .= sprintf(" %02X", $c);
            > } return $hex;
            > }
            >
            >
            >[/color]


            Comment

            Working...