in reply to Re: Math::BigFloat to native double?
in thread Math::BigFloat to native double?

Okay, return as a string and then force perl to numerise it.

Trouble is, something gets lost in the transition:

use Math::BigFLoat;; $n = Math::BigFloat->new( '3.1415926535897932384626433832795' );; print $n;; 3.1415926535897932384626433832795 $d = 0+$n->bstr;; ##### as a double printf "%.17f\n", $d;; ##### display to full precision 3.14159265358979310 $n -= $d;; ##### substract from the bigfloat print $n;; ##### and display the (bigfloat) result 0.0000000000000032384626433832795

But:

3.1415926535897932384626433832795 - 3.1415926535897931000000000000000 0.0000000000000001384626433832795 which is quite different to the +value from above! 0.0000000000000032384626433832795

I expected some minor discrepancies, but not an order of magnitude difference.


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".
In the absence of evidence, opinion is indistinguishable from prejudice.
I'm with torvalds on this Agile (and TDD) debunked I told'em LLVM was the way to go. But did they listen!

Replies are listed 'Best First'.
Re^3: Math::BigFloat to native double?
by syphilis (Archbishop) on Jul 13, 2015 at 01:48 UTC
    but not an order of magnitude difference

    The base 2 representation of 3.1415926535897932384626433832795 is:
    0.1100100100001111110110101010001000100001011010001100001000110100.....e2

    Round that to 53 bits:
    0.11001001000011111101101010100010001000010110100011000e2

    Convert that value back to base 10:
    3.14159265358979311599796...

    I don't know how perl and Math::BigFloat arrive at the values they do, but I do know that off-by-one (or more) ULP errors are not unusual in perl.
    Also, you've stretched the requested precision to 17 decimal digits, which might be a contributing factor - need to think more about that.

    If you want reliable rounding and accuracy with floating point values, use Math::MPFR.

    Cheers,
    Rob
      Also, you've stretched the requested precision to 17 decimal digits, which might be a contributing factor

      After anonymonks post above about printf inventing stuff, I explored the possibility, and from what I can tell, if you ask printf for more precision than is available, it just pads with trailing zeros:

      printf "dp:%u : %35.*f\n", $_, $_, 3.1415926535897932384626433832795 f +or 14 .. 20;; dp:14 : 3.14159265358979 dp:15 : 3.141592653589793 dp:16 : 3.1415926535897931 dp:17 : 3.14159265358979310 dp:18 : 3.141592653589793100 dp:19 : 3.1415926535897931000 dp:20 : 3.14159265358979310000

      And:

      [0] Perl> printf "dp:%u : %.*f\n", $_, $_, 123e-308 for 300 .. 320;; dp:300 : 0.000 {300 zeros ellided} 000000000000 dp:301 : 0.000 {300 zeros ellided} 0000000000000 dp:302 : 0.000 {300 zeros ellided} 00000000000000 dp:303 : 0.000 {300 zeros ellided} 000000000000000 dp:304 : 0.000 {300 zeros ellided} 0000000000000000 dp:305 : 0.000 {300 zeros ellided} 00000000000000000 dp:306 : 0.000 {300 zeros ellided} 000000000000000001 dp:307 : 0.000 {300 zeros ellided} 0000000000000000012 dp:308 : 0.000 {300 zeros ellided} 00000000000000000123 dp:309 : 0.000 {300 zeros ellided} 000000000000000001230 dp:310 : 0.000 {300 zeros ellided} 0000000000000000012300 dp:311 : 0.000 {300 zeros ellided} 00000000000000000123000 dp:312 : 0.000 {300 zeros ellided} 000000000000000001230000 dp:313 : 0.000 {300 zeros ellided} 0000000000000000012300000 dp:314 : 0.000 {300 zeros ellided} 00000000000000000123000000 dp:315 : 0.000 {300 zeros ellided} 000000000000000001230000000 dp:316 : 0.000 {300 zeros ellided} 0000000000000000012300000000 dp:317 : 0.000 {300 zeros ellided} 00000000000000000123000000000 dp:318 : 0.000 {300 zeros ellided} 000000000000000001230000000000 dp:319 : 0.000 {300 zeros ellided} 0000000000000000012300000000000 dp:320 : 0.000 {300 zeros ellided} 00000000000000000123000000000000
      If you want reliable rounding and accuracy with floating point values, use Math::MPFR.

      I was actually hoping for simple truncation. I'm only using Math::BigFloat in an attempt to verify my double-double implementation.

      And what I've realised/discovered is that the mistake is when M::BF translates the double value when performing the subtraction above.

      If I do the translation myself, I get sensible numbers:

      use Math::BigFloat;; $n = Math::BigFloat->new( '3.1415926535897932384626433832795' );; $d = 0 + $n->bstr;; printf "%.17f\n", $d;; 3.14159265358979310 $bfd = Math::BigFloat->new( sprintf "%.17f", $d );; print $bfd;; 3.1415926535897931 $n -= $bfd;; print $n;; 0.0000000000000001384626433832795

      Which gives me:

      3.14159265358979310 + 0.0000000000000001384626433832795 = 3.1415926535897932384626433832795 == 3.141592653589793238462643383 +2795 (the input)

      And that's all I was after.


      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".
      In the absence of evidence, opinion is indistinguishable from prejudice.
      I'm with torvalds on this Agile (and TDD) debunked I told'em LLVM was the way to go. But did they listen!
        And that's all I was after

        If it matters to you (and it may conceivably not), that seems not quite the same as the split that the hardware double-double implementations produce.
        On my double-double (PowerPC) box, for your given 32-digit value of
        3.1415926535897932384626433832795
        the 2 doubles would there round out as
        3.14159265358979e+000 and 1.22464679914735e-016
        with actual hex representations of
        0x1.921fb54442d18p+1 and 0x1.1a62633145c07p-53.

        Those 2 hex values concatenate to the correct 107-bit representation of the original value:
        0.11001001000011111101101010100010001000010110100011000010001101001100 +010011000110011000101000101110000000111E2
        Cheers,
        Rob
Re^3: Math::BigFloat to native double?
by Anonymous Monk on Jul 12, 2015 at 21:31 UTC
    i dunno :) looks like printf is inventing stuff a
    $ perl -le " print 3.1415926535897932384626433832795 3.14159265358979 $ perl -le " printf q{%.17f}, 3.1415926535897932384626433832795 3.14159265358979312 $ perl -le " printf q{%.44f}, 3.1415926535897932384626433832795 3.14159265358979311599796346854418516159057617 $ perl -le " printf q{%.66f}, 3.1415926535897932384626433832795 3.141592653589793115997963468544185161590576171875000000000000000000 $ perl -le " print '3.1415926535897932384626433832795' 3.1415926535897932384626433832795 $
      looks like printf is inventing stuff

      Oh boy! I hadn't even consider that possibility :(


      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".
      In the absence of evidence, opinion is indistinguishable from prejudice.
      I'm with torvalds on this Agile (and TDD) debunked I told'em LLVM was the way to go. But did they listen!
Re^3: Math::BigFloat to native double?
by Laurent_R (Canon) on Jul 12, 2015 at 21:33 UTC
    Hm, I have yet to see a real case where it make sense to calculate pi to the 13th or 14th digit.