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
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: |
| & | | & |
| < | | < |
| > | | > |
| [ | | [ |
| ] | | ] |
Link using PerlMonks shortcuts! What shortcuts can I use for linking?
See Writeup Formatting Tips and other pages linked from there for more info.