.... but swapping entire bytes ...
In addition to the endianness issue, there's also the "precision" issue that can trip one up when print()ing NV values.
On a perl whose nvtype is double:
D:\>perl -le "print unpack 'd', pack 'd', sqrt 2;"
1.4142135623731
On a perl whose nvtype is the 80-bit extended precision long double:
D:\>perl -le "print unpack 'd', pack 'd', sqrt 2;"
1.41421356237309515
On a perl whose nvtype is either the IEEE 754 long double or the __float128:
D:\>perl -le "print unpack 'd', pack 'd', sqrt 2;"
1.41421356237309514547462185873883
You might think that the differences in those 3 one liners occur because pack 'd', sqrt 2 has returned different bytes in each of those 3 one liners, but that's not so.
In each of those 3 one-liners pack 'd', sqrt 2 returned exactly the same byte.
So, it must be that the unpacking returned different values ? Wrong again.
It's the way that perl's print() function conceals the actual value returned by unpack 'd', pack 'd', sqrt 2 that accounts for the anomalies.
Perl is bullshitting in all 3 cases (and knows it).
On a perl whose nvtype is double:
D:\>perl -le "print 'WTF' if (unpack 'd', pack 'd', sqrt 2) != 1.41421
+35623731;"
WTF
On a perl whose nvtype is the 80-bit extended precision long double:
D:\>perl -le "print 'WTF' if (unpack 'd', pack 'd', sqrt 2) != 1.41421
+356237309515;"
WTF
On a perl whose nvtype is either the IEEE 754 long double or the __float128:
D:\>perl -le "print 'WTF' if (unpack 'd', pack 'd', sqrt 2) != 1.41421
+356237309514547462185873883;"
WTF
3 different renditions of the same value - none of them accurate.
I recall a quote (probably from Larry) from a while ago, along the lines of "perl makes the hard things easy".
When it comes to certain aspects of the way perl deals with NVs, it's more a case of "perl makes the easy things hard".
I think it's ridiculous and, although I'm scathing of it, I'm also used to it and sort of like the way that it keeps me on my toes ;-)
So ... for a given $byte, what one expects to be returned by unpack "d", $byte can depend not only upon machine endianness, but also on NV type.
Cheers, Rob
| [reply] [Watch: Dir/Any] [d/l] [select] |
Quick question: The string printed is different, but are the values different? (Like, would you get different output for all three if you used printf "%.10000g\n", unpack 'd', pack 'd', sqrt 2?)
For those that might be interested, this linked code stringifies any double using decimal notation (as opposed to scientific notation). It will return the stored number exactly, or you can specify a precision. I'm not sufficiently familiar with the other two formats you mentioned to know whether it will work with them, but I think it will if you specify a precision. The default precision will definitely needs to be adjusted to support those formats.
| [reply] [Watch: Dir/Any] [d/l] |
would you get different output for all three if you used printf "%.10000g\n", unpack 'd', pack 'd', sqrt 2 ?
As is desirable, it's the same (and correct) output in all three cases:
D:\>perl -le "printf '%.10000g', unpack 'd', pack 'd', sqrt 2;"
1.4142135623730951454746218587388284504413604736328125
which, incidentally, is exactly the value of the double precision representation of sqrt 2.
Cheers, Rob | [reply] [Watch: Dir/Any] [d/l] [select] |