You will need to determine what format the long doubles are in, and the byte-ordering of the platform that is writing them.

There are many 128-bit real formats around.

There are others besides these, including some mainframes use a kind of binary coded decimal format.

To compound the problem, there is no defined "network format" for reals, so when they are written to storage in native format, they tend to be byte-order dependant. Even if you write a 64-bit real using pack 'd' format on a little-endian platform, you will not be able to directly unpack it using 'd' on a big-endian platform.

Once you know the format and endianess of the data, the easiest way to unpack it would be to transform it into a ascii-ized bitstring, break it up into its component parts, and then reconstitute it from there.

By way of example of what you need to do, the following code constructs some random 64-bit reals and then decodes them without using pack 'd'.

The output compares pack 'd' with the results from my real8ToDouble() routine.

#! perl -slw use strict; sub real8ToDouble { my( $real8 ) = shift; my $bits = reverse unpack 'b64', $real8; # IEEE 754 64-bit real (double) format # seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff f +fffffff #1-sign 11- mantissa 52-bits (+1 implicit) binary fraction my( $sign, $exp, $frac ) = $bits =~ m[(.)(.{11})(.{52})]; my $expAsInt = unpack( 'v', pack 'b16', scalar reverse $exp ) - 10 +23; my $f = 1; my $n = 1; for my $bp ( split '', $frac ) { $n /= 2; $f += $n if $bp; } return ( $f * 2**$expAsInt ) * ( $sign ? -1 : 1 ); } for ( 1 .. 20 ) { my( $s, $c, $m ) = ( rand > 0.5 ? '+' : '-', rand, int( rand 600 ) -300 ); my $double = "$s${c}E$m"; printf "%g : %g\n", $double, real8ToDouble( pack 'd', $double ); } __END__ P:\test>452186.pl -3.27454e+126 : -3.27454e+126 -6.33606e-135 : -6.33606e-135 -9.78943e-089 : -9.78943e-089 3.75458e-262 : 3.75458e-262 9.11469e-049 : 9.11469e-049 6.66809e-052 : 6.66809e-052 9.58191e+086 : 9.58191e+086 -7.59277e+284 : -7.59277e+284 3.93188e-021 : 3.93188e-021 -4.28009e-048 : -4.28009e-048 -5.32776e-173 : -5.32776e-173 5.55817e-147 : 5.55817e-147 -4.44031e+060 : -4.44031e+060 2.40295e+126 : 2.40295e+126 8.55194e+132 : 8.55194e+132 5.61005e+184 : 5.61005e+184 -9.57489e-107 : -9.57489e-107 8.71338e+130 : 8.71338e+130 5.66986e+227 : 5.66986e+227 3.41461e-116 : 3.41461e-116

Obviously you will lose some precision going from 128-bits to 64-bits, and extreme values will fall outside of the range a 64-bit real can handle.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco.
Rule 1 has a caveat! -- Who broke the cabal?

In reply to Re: Value packed as 'D', how to unpack not using 'D'? by BrowserUk
in thread Value packed as 'D', how to unpack not using 'D'? by chrism01

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.