Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Re^5: Converting bytes to floats

by stevieb (Canon)
on Apr 18, 2023 at 08:35 UTC ( [id://11151728]=note: print w/replies, xml ) Need Help??


in reply to Re^4: Converting bytes to floats
in thread Converting bytes to floats

struck an endianness issue

Man, this takes me back several years to when I started coding low-level stuff for my microcontroller sensor projects.

Collecting data and flipping bits...fine, but swapping entire bytes!?! :)

Replies are listed 'Best First'.
Re^6: Converting bytes to floats
by syphilis (Archbishop) on Apr 18, 2023 at 12:38 UTC
    .... 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

      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.

        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

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11151728]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (7)
As of 2024-03-28 10:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found