If we limit ourselves to Math::BigFloat, I just don't see any easy way of escaping the fact that, in i2dd(), Math::BigFloat->new( sprintf "%.17f", $hi ) is simply not a good enough base 10 approximation of $hi.

For the given example, you're subtracting 3.1415926535897931000000000000000 from 3.1415926535897932384626433832795 in order to get the least significant double.
But you need to be subtracting 3.1415926535897931159979634685442 which is a far more accurate base 10 approximation of 0x1.921fb54442d18p+1. That results in a value of 0.0000000000000001224646799147353, which has a hex representation of 0x1.1a62633145c06p-53. Correctly it would be 0x1.1a62633145c07p-53 - the discrepancy being due to the rounding done in converting to base 10 values for the calculations.

In any case, the problem is that I can't see any simple way of coercing Math::BigFloat into arriving at more accurate values - as it apparently can't convert hex floats to Math::BigFloat values.

All of which brings me back to using something like mpfr.
AFAIK, my Math::MPFR ppm packages will work fine with your MSVC-built perls, but it has probably been a while since this has been properly tested.
The ppd file specifies a couple of prerequisites to install, one of which (Math::Float128) may not work correctly for you. The other is Math::Decimal64.
If you want to avoid installing those pre-requisite modules, just save a copy of my scratchpad in the cwd as Math-MPFR.ppd and run:
ppm install Math-MPFR.ppd --force
Otherwise you can run:
ppm install http://www.sisyphusion.tk/ppm/Math-Decimal64.ppd --force
ppm install http://www.sisyphusion.tk/ppm/Math-Float128.ppd --force
ppm install http://www.sisyphusion.tk/ppm/Math-MPFR.ppd --force
The prerequisites are needed only if you want to call a function that takes/returns a Math::Float128 or Math::Decimal64 object. (I don't foresee that you have any need to be calling those functions.)

I fully understand and really don't mind at all if you don't want to go down that path - and I'm sure that other alternatives exist.
But I'm pretty much out of ideas (and energy) if Math::MPFR is to be excluded. (Without it, there's just too many hoops for me).
With Math::MPFR installed, sub i2dd becomes (eg):
sub i2dd { use Math::MPFR qw(:mpfr); my $prec = Rmpfr_get_default_prec(); Rmpfr_set_default_prec(2098); my $val = Math::MPFR->new($_[0]); my $hi = Rmpfr_get_d($val, MPFR_RNDN); $val -= $hi; my $lo = Rmpfr_get_d($val, MPFR_RNDN); # Revert to original precision: Rmpfr_set_default_prec($prec); return($hi, $lo); }
(Of course, the sub can be set up to operate more efficiently than as presented - I just wanted it to cover all angles.)

Cheers,
Rob

In reply to Re^12: Math::BigFloat to native double? by syphilis
in thread Math::BigFloat to native double? by BrowserUk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.