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.
I cannot relocate that description now.
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.
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
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |