syphilis has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

With python3 installed, I'm able to access (from within a perl script) the values that python3 prints out for a particular double ($d) by shelling out as follows:
use strict; use warnings; my $d = 2 ** -1074; my $py = `python3 -c \"print($d)\"`; print "$py\n"; # prints 5e-324
Now, that's about the full extent of my python3 skills, and it works well enough for my purposes even though shelling out is quite an expensive operation.

But that only works as I intend if $d is a 'double' - ie when $Config{nvtype} is 'double'.
How do I get access to the output of 'long double' and '__float128' values in python3 - ie when perl's nvtype (and hence $d) is 'long double' or '__float128' ?
I couldn't quickly google up an answer to that question ... so I'm asking here in the event that some kind soul might be able to help me out.

<pathetic cringe>
By way of explanation:
Python3 has a rather nice approach to the (base 10) presentation of floating point values. It will provide as few digits as are needed. The script above is a good example. Perl will tell you:
C:\>perl -le "print 2 ** -1074;" 4.94065645841247e-324
And python3 will claim:
$ python3 -c "print(2 ** -1074)" 5e-324
The 2 values appear to be different ... but they're not, and perl will even tell you so:
C:\>perl -le "print 'ok' if 5e-324 == 4.94065645841247e-324;" ok
It therefore begs the question "Why go to the (obfuscating ?) trouble of providing all of those extra digits when they don't provide greater accuracy ?". It's a good question - though there are answers and the question is
not necessarily a rhetorical one.

Anyway, I've written a perl implementation (using Math::MPFR, Math::GMPz, Math::GMPq) of the python3 approach to base 10 output of floating point values, and I need to test it.
The internal consistency checks are looking fine, but I also want to check against some trustworthy external source - largely to check that I've got the standardised output working as per the .... ummm .... standard.
That's why I'm referencing python3, and it's checking out well for double precision floating point values.
Now it's just a matter of checking the 'long double' and '__float128' precision values.
Hence my request for assistance.
</pathetic cringe>

Is there a better "trustworthy external source" that I should be using ?
Is there a C library available that already implements this algorithm ? (Note that the PDF file to which I've linked provides only pages 112-126 of the book. I've implemented the algorithm on page 120.)
Incidentally, Zefram had indicated an interest in implementing this particular algorithm into the perl source, but I've seen no postings from him anywhere since his perl5 grant ran out last year.

Cheers,
Rob

Replies are listed 'Best First'.
Re: [OT] Accessing python3's print() of floating point values
by Tux (Canon) on Jan 18, 2019 at 15:37 UTC
    $ perl -wE'printf"%.0e\n",2 ** -1074' 5e-324

    Enjoy, Have FUN! H.Merijn
      $ perl -wE'printf"%.0e\n",2 ** -1074'

      Yes, if you know in advance the minimum number of digits needed then you can certainly feed that precision to printf() as you have done.
      But, in general, one doesn't know that number.

      For the given example, "%.0e" is fine because the following condition is true when $prec is 0:
      sprintf "%.${prec}e", 2 ** -1074 == 2 ** -1074
      But replace "2 ** -1074" with "3 ** 0.5", and the condition is untrue if $prec is 0. What's the minimum value for $prec that will render the condition true for 3 ** 0.5 ?
      I haven't checked, but if nvtype is "double" it's probably 16, definitely not greater than 16, and unlikely to be less than 15.
      Python3 (and the algorithm I've coded up) will output that minimum precision, without the need for anyone to calculate a "$prec" and feed it to printf().

      Only thing I don't currently have is access to a widely available and well tested implementation of the algorithm for "long double" and "__float128" NVs - one that I can use to double-check that my own implementation is behaving correctly and standardizing the output appropriately.
      And that's what I'm seeking.

      Cheers,
      Rob
Re: [OT] Accessing python3's print() of floating point values
by Anonymous Monk on Jan 18, 2019 at 15:19 UTC

    Hi,

    Use perl6:

    perl6 -e "say 2 ** -1074"

    Outputs: 5e-324

      perl6 -e "say 2 ** -1074"

      Kudos to perl6 if it's now implementing the algorithm that outputs as few decimal digits as are necessary.
      My older perl6 (Perl 6.c) gives me:
      $ perl6 -e "say 2 ** -1074" Numeric overflow in block <unit> at -e line 1 Actually thrown at: in block <unit> at -e line 1
      What does your perl6 output for:
      perl6 -e "say 2 ** 0.5"
      Does perl6 yet provide "long double" and "__float128" builds ? They are the types I'm currently unable to independently verify.
      (As I mentioned in my original post, for "doubles" I can already verify my outputs against python3.)

      Cheers,
      Rob

        I use perl6::version=2018.04.1 and also perl6::version=2018.10.1

        The results for version 2018.04.1 (isn't this rather old?) are:

        For perl6 -e "say 2 ** 0.5": 1.4142135623730951

        For perl6 -e "say 2 ** -1074": 5e-324

        So you should give a somewhat newer version a try

        My results are from the rakudo-star-2018.04-x86_64 (JIT).msi on Windows