Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re^2: Determining the minimum representable increment/decrement possible? (Perl's scanf broken?)

by BrowserUk (Patriarch)
on Jun 17, 2016 at 13:41 UTC ( [id://1165975]=note: print w/replies, xml ) Need Help??


in reply to Re: Determining the minimum representable increment/decrement possible?
in thread Determining the minimum representable increment/decrement possible?

Indeed. The previous post was done using 5.10.1; this is 5.22:

C:\Program Files>\Perl22\bin\perl.exe \perl22\bin\p1.pl printf "% 25.17g\n", -8.2727285363069939e-293;; -8.2727285363069883e-293 ## manually reali +gned to highlight the difference. [0]{} Perl>

Of more importance is the source of the numbers that apparently cannot be represented by 64-bit floating point. At least in perl.

They are produced & output by the C++ code I'm optimising. I originally thought that the C++ math was producing denormals and C++ was outputting them unnormalised, but that does not seem to be the case:

print join ' ', unpack 'a1 a11 a52', scalar reverse unpack 'b64', pack + 'd', $_ for -8.2727285363069939e-293, -8.2727285363069883e-293;; 1 00000110100 1010011010101110110010001111100101000001001101001100 1 00000110100 1010011010101110110010001111100101000001001101000111

Even the latest perl seems just to be getting the conversion wrong!? Both numbers are representable with 64-bit Ieee754 numbers, so why Perl should silently convert one to the other is something of a mystery. Basically, Perl's (or the underlying CRT) input routine just seems to be broken.

Update: The 5.22 perl I'm using is built with the same compiler and libraries as the C++ code; so this seems to be a PerlIO issue rather than a CRT issue.


With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
In the absence of evidence, opinion is indistinguishable from prejudice. Not understood.
  • Comment on Re^2: Determining the minimum representable increment/decrement possible? (Perl's scanf broken?)
  • Select or Download Code

Replies are listed 'Best First'.
Re^3: Determining the minimum representable increment/decrement possible? (Perl's scanf broken?)
by syphilis (Archbishop) on Jun 17, 2016 at 14:37 UTC
    printf "% 25.17g\n", -8.2727285363069939e-293;;
    -8.2727285363069883e-293


    Yeah, I get the same with mingw-built x64 5.22.0.
    This is the perl bug I alluded to in my first post that mis-assigns values by up to a few ULPs.
    If you check the hex format (assigned by perl) of -8.2727285363069939e-293 you'll find:
    C:\_32>perl -le "print scalar reverse unpack 'h*', pack 'd<', -8.27272 +85363069939e-293;" 834a6aec8f94134c
    However, the correct hex format of -8.2727285363069939e-293 is 834a6aec8f941351.
    834a6aec8f94134c does in fact correspond to -8.2727285363069883e-293 - so perl is doing the conversion from internal form to decimal string correctly. It's just the initial conversion from decimal string to internal form that was incorrect.

    Sadly, no-one seems interested in fixing this - though I think that's because of the degree of difficulty rather than actual "disinterest".
    If this level of inaccuracy bothers you (as it does me) then one solution is to assign using POSIX::strtod:
    C:\_32>perl -MPOSIX -le "print scalar reverse unpack 'h*', pack 'd<', +POSIX::strtod('-8.2727285363069939e-293');" 834a6aec8f941351 C:\_32>perl -MPOSIX -le "printf '% 25.17g', POSIX::strtod('-8.27272853 +63069939e-293');" -8.2727285363069939e-293
    This way you put your faith in the C compiler and that seems to be a safer bet.
    (That's probably good enough, though I'd rather put my faith in the mpfr library.)

    Cheers,
    Rob
      Sadly, no-one seems interested in fixing this - though I think that's because of the degree of difficulty rather than actual "disinterest".

      I'm somewhat confused by that. Why not use the underlying CRTs sscanf() or strtod()?

      one solution is to assign using POSIX::strtod

      That's very useful! Thankyou.

      I'd rather put my faith in the mpfr library.

      For the most part, I'm only really using Perl as an interactive calculator for exploring the issues; the actual code is C++; and I'm doing some optimisations in x64 assembler.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
      In the absence of evidence, opinion is indistinguishable from prejudice. Not understood.
        Why not use the underlying CRTs sscanf() or strtod()?

        I don't know.
        I speculate that in earlier times those functions were not so reliable and it was decided that perl should do its own implementation.
        I further speculate that it has now got to the stage that unwinding that perl implementation is not a trivial task.

        Cheers,
        Rob

        Why not use the underlying CRTs sscanf() or strtod()?

        I think differences in stringifications of Inf and NaN played a roll.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (7)
As of 2024-04-24 17:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found