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

How do I coerce a Math::BigFloat value (within the suitable range) back to a native double?


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: Math::BigFloat to native double?
by Anonymous Monk on Jul 12, 2015 at 20:21 UTC
    use Math::BigFloat; use Data::Dump qw/ dd /; my $bf = Math::BigFloat->new(q{6.66666666666666666666666666666666}); dd( $bf, $bf->bstr, $bf->bstr+0, "$bf"+0 ); __END__ ( bless({ _e => [32], _es => "-", _m => [6666666, 6666666, 6666666, 6666666, 66666], sign => "+", }, "Math::BigFloat"), "6.66666666666666666666666666666666", 6.66666666666667, 6.66666666666667, )

      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!
        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
        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 $
        Hm, I have yet to see a real case where it make sense to calculate pi to the 13th or 14th digit.