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

That makes no sense to me at all

It was a poorly expressed explanation.
The most significant double is 0x1.921fb54442d18p+1. (We agree on this, at least.)
That string expresses an exact value, but 3.1415926535897931 is only a very poor approximation of that exact value.
The least significant double is, according to me, 0x1.1a62633145c07p-53.
That string expresses an exact value, but 1.2246467991473532e-16 is only a very poor approximation of that exact value.
So ... my doubledouble contains a value that is exactly the sum of both:
0x1.921fb54442d18p+1 + 0x1.1a62633145c07p-53
But you can't expect the sum of the 2 rough decimal approximations to be equivalent to the exact hex sum of the 2 hex numbers. (And it's not, of course.)

The least significant double that your approach came up with was 0x1.3f45eb146ba31p-53.
Your decimal approximation of that exact value is 0.0000000000000001384626433832795.
When you add your 2 decimal approximations together you end up with the input value - but that's false comfort.
The actual value contained by your doubledouble is, according to the way I look at them, is not really the sum of the 2 decimal approximations - it's the sum of the 2 hex values:
0x1.921fb54442d18p+1 + 0x1.3f45eb146ba31p-53.
That corresponds to a base 10 value of 3.141592653589793254460606851823683 (which differs significantly from the input).
Your doubledouble, expressed in base 2 is:
11.001001000011111101101010100010001000010110100011000010011111101000101111010110001010001101011101000110001
which is not the correct 107 bit representation of the input value.
If you use that doubledouble as your pi approximation, then you'll only get incorrect results.

FWIW, if I want to calculate the double-double representation of a specific value, I do essentially the same as you, except that I use Math::MPFR instead of Math::BigFloat.
And I set precision to 2098 bits. I have:
# sub dd_str takes a string as its arg and returns # the 2 doubles that form the doubledouble. # Works correctly if default Math::MPFR precision is # 2098 bits - else might return incorrect values. sub dd_str { # Set $val to the 2098 bit representation of $_[0] my $val = Math::MPFR->new($_[0]); # Most significant double is $val converted to a # double, rounding to nearest with ties to even my $msd = Rmpfr_get_d($val, MPFR_RNDN); $val -= $msd; # Least siginificant double is $val converted # to a double. return ($msd, Rmpfr_get_d($val, MPFR_RNDN)); }
2098 bits is overkill for the vast majority of conversions. It stems from the fact that the doubledouble can accurately represent certain values up to (but not exceeding) 2098 bits.
For example, on my PPC box I can assign  $x = (2 **1023) + (2 ** -1074); and the doubledouble $x will consist of the 2 doubles 2**1023 and 2**-1074, thereby accurately representing that 2098 bit value.
The value of this capability is limited - multiply $x by (say) 1.01 and all of that additional precision is lost. The result is the same as multiplying 2**1023 by 1.01.

Anyway ... first question is "how to set your doubledouble pi correctly using Math::BigFloat ?".

I couldn't quickly come up with an answer, but I'll give it some more thought later on today.

Cheers,
Rob

Replies are listed 'Best First'.
Re^11: Math::BigFloat to native double?
by BrowserUk (Patriarch) on Jul 14, 2015 at 05:11 UTC

    This is what I have so far for my input/output routines:

    #! perl -slw use strict; no warnings 'portable'; use Math::BigFloat; use Data::Dump qw[ pp ]; my @lookup = map{ Math::BigFloat->new( "$_" ) } <DATA>; # pp \@lookup; sub dd2dec { my( $hi, $lo ) = @_; my( $hiSign, $hiExp, $hiMant ) = unpack 'a1a11a52', unpack 'B64', +reverse pack 'd', $hi; $hiExp = unpack 'v', pack 'b11', $hiExp; print $hiExp; my $loMant = unpack 'x12a52', unpack 'B64', reverse pack 'd', $lo; print $hiMant, ' ', $loMant; my $dec = $lookup[ 0 ]; substr( $hiMant, $_, 1 ) eq '1' and $dec += $lookup[ $_+1 ] for 0 +.. 51; #$dec += $lookup[ 52 ]; #substr( $loMant, $_, 1 ) eq '1' and $dec += $lookup[ $_+51 ] for +0 .. 51; $dec += 4; return $dec->bstr; } sub FP2bin{ sprintf "%s %35.17e", join( ' ', unpack 'a1a11a52', unpack + 'B64', reverse pack 'd', $_[0] ), $_[0]; } sub i2dd { my $bf = Math::BigFloat->new( shift ); my $hi = 0 + $bf->bstr; $bf -= Math::BigFloat->new( sprintf "%.17f", $hi ); my $lo = 0 + $bf->bstr; return ( $hi, $lo ); } sub d2Hex{ my $fp = shift; my $bin = unpack 'Q', pack 'd', $fp; my( $sign, $exp, $mant ) = ( ( ( $bin & 0x8000000000000000 ) ? '-' : '' ), ( ( ( $bin & 0x7FF0000000000000 ) >> 52 ) - 1023 ), ( $bin & 0x000FFFFFFFFFFFFF ) ); sprintf "%s0x1.%xp%d", $sign, $mant, $exp; } print join "\n", map{ FP2bin( $_ ) } i2dd( '3.141592653589793238462643 +3832795' ); print join "\n", map{ d2Hex( $_ ) } i2dd( '3.1415926535897932384626433 +832795' ); __DATA__ 0.5 0.25 0.125 0.0625 0.03125 0.015625 0.0078125 0.00390625 0.001953125 0.0009765625 0.00048828125 0.000244140625 0.0001220703125 0.00006103515625 0.000030517578125 0.0000152587890625 0.00000762939453125 0.000003814697265625 0.0000019073486328125 0.00000095367431640625 0.000000476837158203125 0.0000002384185791015625 0.00000011920928955078125 0.000000059604644775390625 0.0000000298023223876953125 0.00000001490116119384765625 0.000000007450580596923828125 0.0000000037252902984619140625 0.00000000186264514923095703125 0.000000000931322574615478515625 0.0000000004656612873077392578125 0.00000000023283064365386962890625 0.000000000116415321826934814453125 0.0000000000582076609134674072265625 0.00000000002910383045673370361328125 0.000000000014551915228366851806640625 0.0000000000072759576141834259033203125 0.00000000000363797880709171295166015625 0.000000000001818989403545856475830078125 0.0000000000009094947017729282379150390625 0.00000000000045474735088646411895751953125 0.000000000000227373675443232059478759765625 0.0000000000001136868377216160297393798828125 0.00000000000005684341886080801486968994140625 0.000000000000028421709430404007434844970703125 0.0000000000000142108547152020037174224853515625 0.00000000000000710542735760100185871124267578125 0.000000000000003552713678800500929355621337890625 0.0000000000000017763568394002504646778106689453125 0.00000000000000088817841970012523233890533447265625 0.000000000000000444089209850062616169452667236328125 0.0000000000000002220446049250313080847263336181640625 0.00000000000000011102230246251565404236316680908203125 0.000000000000000055511151231257827021181583404541015625 0.0000000000000000277555756156289135105907917022705078125 0.00000000000000001387778780781445675529539585113525390625 0.000000000000000006938893903907228377647697925567626953125 0.0000000000000000034694469519536141888238489627838134765625 0.00000000000000000173472347597680709441192448139190673828125 0.000000000000000000867361737988403547205962240695953369140625 0.0000000000000000004336808689942017736029811203479766845703125 0.00000000000000000021684043449710088680149056017398834228515625 0.000000000000000000108420217248550443400745280086994171142578125 0.0000000000000000000542101086242752217003726400434970855712890625 0.00000000000000000002710505431213761085018632002174854278564453125 0.000000000000000000013552527156068805425093160010874271392822265625 0.0000000000000000000067762635780344027125465800054371356964111328125 0.00000000000000000000338813178901720135627329000271856784820556640625 0.00000000000000000000169406589450860067813664500135928392410278320312 +5 0.00000000000000000000084703294725430033906832250067964196205139160156 +25 0.00000000000000000000042351647362715016953416125033982098102569580078 +125 0.00000000000000000000021175823681357508476708062516991049051284790039 +0625 0.00000000000000000000010587911840678754238354031258495524525642395019 +53125 0.00000000000000000000005293955920339377119177015629247762262821197509 +765625 0.00000000000000000000002646977960169688559588507814623881131410598754 +8828125 0.00000000000000000000001323488980084844279794253907311940565705299377 +44140625 0.00000000000000000000000661744490042422139897126953655970282852649688 +720703125 0.00000000000000000000000330872245021211069948563476827985141426324844 +3603515625 0.00000000000000000000000165436122510605534974281738413992570713162422 +18017578125 0.00000000000000000000000082718061255302767487140869206996285356581211 +090087890625 0.00000000000000000000000041359030627651383743570434603498142678290605 +5450439453125 0.00000000000000000000000020679515313825691871785217301749071339145302 +77252197265625 0.00000000000000000000000010339757656912845935892608650874535669572651 +386260986328125 0.00000000000000000000000005169878828456422967946304325437267834786325 +6931304931640625 0.00000000000000000000000002584939414228211483973152162718633917393162 +84656524658203125 0.00000000000000000000000001292469707114105741986576081359316958696581 +423282623291015625 0.00000000000000000000000000646234853557052870993288040679658479348290 +7116413116455078125 0.00000000000000000000000000323117426778526435496644020339829239674145 +35582065582275390625 0.00000000000000000000000000161558713389263217748322010169914619837072 +677910327911376953125 0.00000000000000000000000000080779356694631608874161005084957309918536 +3389551639556884765625 0.00000000000000000000000000040389678347315804437080502542478654959268 +16947758197784423828125 0.00000000000000000000000000020194839173657902218540251271239327479634 +084738790988922119140625 0.00000000000000000000000000010097419586828951109270125635619663739817 +0423693954944610595703125 0.00000000000000000000000000005048709793414475554635062817809831869908 +52118469774723052978515625 0.00000000000000000000000000002524354896707237777317531408904915934954 +260592348873615264892578125 0.00000000000000000000000000001262177448353618888658765704452457967477 +1302961744368076324462890625 0.00000000000000000000000000000631088724176809444329382852226228983738 +56514808721840381622314453125 0.00000000000000000000000000000315544362088404722164691426113114491869 +282574043609201908111572265625 0.00000000000000000000000000000157772181044202361082345713056557245934 +6412870218046009540557861328125 0.00000000000000000000000000000078886090522101180541172856528278622967 +32064351090230047702789306640625 0.00000000000000000000000000000039443045261050590270586428264139311483 +660321755451150238513946533203125 0.00000000000000000000000000000019721522630525295135293214132069655741 +8301608777255751192569732666015625 0.00000000000000000000000000000009860761315262647567646607066034827870 +91508043886278755962848663330078125 0.00000000000000000000000000000004930380657631323783823303533017413935 +457540219431393779814243316650390625 0.00000000000000000000000000000002465190328815661891911651766508706967 +7287701097156968899071216583251953125 0.00000000000000000000000000000001232595164407830945955825883254353483 +86438505485784844495356082916259765625 0.00000000000000000000000000000000616297582203915472977912941627176741 +932192527428924222476780414581298828125 0.00000000000000000000000000000000308148791101957736488956470813588370 +9660962637144621112383902072906494140625 0.00000000000000000000000000000000154074395550978868244478235406794185 +48304813185723105561919510364532470703125 0.00000000000000000000000000000000077037197775489434122239117703397092 +741524065928615527809597551822662353515625 0.00000000000000000000000000000000038518598887744717061119558851698546 +3707620329643077639047987759113311767578125 0.00000000000000000000000000000000019259299443872358530559779425849273 +18538101648215388195239938795566558837890625 0.00000000000000000000000000000000009629649721936179265279889712924636 +592690508241076940976199693977832794189453125 0.00000000000000000000000000000000004814824860968089632639944856462318 +2963452541205384704880998469889163970947265625 0.00000000000000000000000000000000002407412430484044816319972428231159 +14817262706026923524404992349445819854736328125 0.00000000000000000000000000000000001203706215242022408159986214115579 +574086313530134617622024961747229099273681640625 0.00000000000000000000000000000000000601853107621011204079993107057789 +7870431567650673088110124808736145496368408203125 0.00000000000000000000000000000000000300926553810505602039996553528894 +89352157838253365440550624043680727481842041015625 0.00000000000000000000000000000000000150463276905252801019998276764447 +446760789191266827202753120218403637409210205078125 0.00000000000000000000000000000000000075231638452626400509999138382223 +7233803945956334136013765601092018187046051025390625 0.00000000000000000000000000000000000037615819226313200254999569191111 +86169019729781670680068828005460090935230255126953125 0.00000000000000000000000000000000000018807909613156600127499784595555 +930845098648908353400344140027300454676151275634765625 0.00000000000000000000000000000000000009403954806578300063749892297777 +9654225493244541767001720700136502273380756378173828125 0.00000000000000000000000000000000000004701977403289150031874946148888 +98271127466222708835008603500682511366903781890869140625 0.00000000000000000000000000000000000002350988701644575015937473074444 +491355637331113544175043017503412556834518909454345703125 0.00000000000000000000000000000000000001175494350822287507968736537222 +2456778186655567720875215087517062784172594547271728515625 0.00000000000000000000000000000000000000587747175411143753984368268611 +12283890933277838604376075437585313920862972736358642578125

    The names don't make much sense at the moment but

    1. dd2Dec() is intended to convert a doubledouble to decimal.

      Not Working yet.

      I produced the set of constant in __DATA__ using M::BF with div_scale set 100.

    2. FP2bin() just dumps the contents of a double as binary fields.
    3. i2dd() takes string and uses M::BF to split it to a pair of doubles.

      Seems to work (for pi); but I'm conscious of your statements above.

    4. d2Hex() double to hex notation.

    And this is the output from the above and the decimal calculation that appears to show it works:

    C:\test>ddt 0 10000000000 1001001000011111101101010100010001000010110100011000 + 3.14159265358979310e+000 0 01111001010 0011111101000101111010110001010001101011101000110001 + 1.38462643383279500e-016 0x1.921fb54442d18p1 0x1.3f45eb146ba31p-53 3.1415926535897931000000000000000 0.0000000000000001384626433832795 3.1415926535897932384626433832795 Calculated 3.1415926535897932384626433832795 Input

    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!
      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
        By my reckoning, this produces a correct doubledouble for 3.1415926535897932384626433832795 - and it uses only Math::BIgFloat.
        It relies on %a printf formatting, so requires perl 5.22.0.
        use strict; use warnings; use Math::BigFloat; use 5.22.0; my %bits_table = ( 1 => '0001', 2 => '0010', 3 => '0011', 4 => '0100', 5 => '0101', 6 => '0110', 7 => '0111', 8 => '1000', 9 => '1001', a => '1010', A => '1010', b => '1011', B => '1011', c => '1100', C => '1100', d => '1101', D => '1101', e => '1110', E => '1110', f => '1111', F => '1111', ); my %vals_table = ( 0 => '1', 1 => '0.5', 2 => '0.25', 3 => '0.125', 4 => '0.0625', 5 => '0.03125', 6 => '0.015625', 7 => '0.0078125', 8 => '0.00390625', 9 => '0.001953125', 10 => '0.0009765625', 11 => '0.00048828125', 12 => '0.000244140625', 13 => '0.0001220703125', 14 => '0.00006103515625', 15 => '0.000030517578125', 16 => '0.0000152587890625', 17 => '0.00000762939453125', 18 => '0.000003814697265625', 19 => '0.0000019073486328125', 20 => '0.00000095367431640625', 21 => '0.000000476837158203125', 22 => '0.0000002384185791015625', 23 => '0.00000011920928955078125', 24 => '0.000000059604644775390625', 25 => '0.0000000298023223876953125', 26 => '0.00000001490116119384765625', 27 => '0.000000007450580596923828125', 28 => '0.0000000037252902984619140625', 29 => '0.00000000186264514923095703125', 30 => '0.000000000931322574615478515625', 31 => '0.0000000004656612873077392578125', 32 => '0.00000000023283064365386962890625', 33 => '0.000000000116415321826934814453125', 34 => '0.0000000000582076609134674072265625', 35 => '0.00000000002910383045673370361328125', 36 => '0.000000000014551915228366851806640625', 37 => '0.0000000000072759576141834259033203125', 38 => '0.00000000000363797880709171295166015625', 39 => '0.000000000001818989403545856475830078125', 40 => '0.0000000000009094947017729282379150390625', 41 => '0.00000000000045474735088646411895751953125', 42 => '0.000000000000227373675443232059478759765625', 43 => '0.0000000000001136868377216160297393798828125', 44 => '0.00000000000005684341886080801486968994140625', 45 => '0.000000000000028421709430404007434844970703125', 46 => '0.0000000000000142108547152020037174224853515625', 47 => '0.00000000000000710542735760100185871124267578125', 48 => '0.000000000000003552713678800500929355621337890625', 49 => '0.0000000000000017763568394002504646778106689453125', 50 => '0.00000000000000088817841970012523233890533447265625', 51 => '0.000000000000000444089209850062616169452667236328125', 52 => '0.0000000000000002220446049250313080847263336181640625', 53 => '0.00000000000000011102230246251565404236316680908203125', 54 => '0.000000000000000055511151231257827021181583404541015625', 55 => '0.0000000000000000277555756156289135105907917022705078125', 56 => '0.00000000000000001387778780781445675529539585113525390625', 57 => '0.000000000000000006938893903907228377647697925567626953125', 58 => '0.0000000000000000034694469519536141888238489627838134765625', 59 => '0.00000000000000000173472347597680709441192448139190673828125', 60 => '0.000000000000000000867361737988403547205962240695953369140625' +, 61 => '0.0000000000000000004336808689942017736029811203479766845703125 +', 62 => '0.0000000000000000002168404344971008868014905601739883422851562 +5', 63 => '0.0000000000000000001084202172485504434007452800869941711425781 +25', 64 => '0.0000000000000000000542101086242752217003726400434970855712890 +625', 65 => '0.0000000000000000000271050543121376108501863200217485427856445 +3125', 66 => '0.0000000000000000000135525271560688054250931600108742713928222 +65625', 67 => '0.0000000000000000000067762635780344027125465800054371356964111 +328125', 68 => '0.0000000000000000000033881317890172013562732900027185678482055 +6640625', 69 => '0.0000000000000000000016940658945086006781366450013592839241027 +83203125', 70 => '0.0000000000000000000008470329472543003390683225006796419620513 +916015625', 71 => '0.0000000000000000000004235164736271501695341612503398209810256 +9580078125', 72 => '0.0000000000000000000002117582368135750847670806251699104905128 +4790039062', 73 => '0.0000000000000000000001058791184067875423835403125849552452564 +2395019531', 74 => '0.0000000000000000000000529395592033937711917701562924776226282 +11975097656', 75 => '0.0000000000000000000000264697796016968855958850781462388113141 +05987548828', 76 => '0.0000000000000000000000132348898008484427979425390731194056570 +52993774414', 77 => '0.0000000000000000000000066174449004242213989712695365597028285 +26496887207', 78 => '0.0000000000000000000000033087224502121106994856347682798514142 +632484436035', 79 => '0.0000000000000000000000016543612251060553497428173841399257071 +316242218018', 80 => '0.0000000000000000000000008271806125530276748714086920699628535 +6581211090088', 81 => '0.0000000000000000000000004135903062765138374357043460349814267 +8290605545044', 82 => '0.0000000000000000000000002067951531382569187178521730174907133 +9145302772522', 83 => '0.0000000000000000000000001033975765691284593589260865087453566 +9572651386261', 84 => '0.0000000000000000000000000516987882845642296794630432543726783 +47863256931305', 85 => '0.0000000000000000000000000258493941422821148397315216271863391 +73931628465652', 86 => '0.0000000000000000000000000129246970711410574198657608135931695 +86965814232826', 87 => '0.0000000000000000000000000064623485355705287099328804067965847 +934829071164131', 88 => '0.0000000000000000000000000032311742677852643549664402033982923 +967414535582066', 89 => '0.0000000000000000000000000016155871338926321774832201016991461 +983707267791033', 90 => '0.0000000000000000000000000008077935669463160887416100508495730 +9918536338955164', 91 => '0.0000000000000000000000000004038967834731580443708050254247865 +4959268169477582', 92 => '0.0000000000000000000000000002019483917365790221854025127123932 +7479634084738791', 93 => '0.0000000000000000000000000001009741958682895110927012563561966 +3739817042369395', 94 => '0.0000000000000000000000000000504870979341447555463506281780983 +18699085211846977', 95 => '0.0000000000000000000000000000252435489670723777731753140890491 +59349542605923489', 96 => '0.0000000000000000000000000000126217744835361888865876570445245 +79674771302961744', 97 => '0.0000000000000000000000000000063108872417680944432938285222622 +898373856514808722', 98 => '0.0000000000000000000000000000031554436208840472216469142611311 +449186928257404361', 99 => '0.0000000000000000000000000000015777218104420236108234571305655 +72459346412870218', 100 => '0.000000000000000000000000000000788860905221011805411728565282 +78622967320643510902', 101 => '0.000000000000000000000000000000394430452610505902705864282641 +39311483660321755451', 102 => '0.000000000000000000000000000000197215226305252951352932141320 +69655741830160877726', 103 => '0.000000000000000000000000000000098607613152626475676466070660 +348278709150804388628', 104 => '0.000000000000000000000000000000049303806576313237838233035330 +174139354575402194314', 105 => '0.000000000000000000000000000000024651903288156618919116517665 +087069677287701097157', 106 => '0.000000000000000000000000000000012325951644078309459558258832 +543534838643850548578', 107 => '0.000000000000000000000000000000006162975822039154729779129416 +2717674193219252742892', 108 => '0.000000000000000000000000000000003081487911019577364889564708 +1358837096609626371446', 109 => '0.000000000000000000000000000000001540743955509788682444782354 +0679418548304813185723', 110 => '0.000000000000000000000000000000000770371977754894341222391177 +03397092741524065928616', 111 => '0.000000000000000000000000000000000385185988877447170611195588 +51698546370762032964308', 112 => '0.000000000000000000000000000000000192592994438723585305597794 +25849273185381016482154', 113 => '0.000000000000000000000000000000000096296497219361792652798897 +129246365926905082410769', 114 => '0.000000000000000000000000000000000048148248609680896326399448 +564623182963452541205385', 115 => '0.000000000000000000000000000000000024074124304840448163199724 +282311591481726270602692', 116 => '0.000000000000000000000000000000000012037062152420224081599862 +141155795740863135301346', 117 => '0.000000000000000000000000000000000006018531076210112040799931 +0705778978704315676506731', 118 => '0.000000000000000000000000000000000003009265538105056020399965 +5352889489352157838253365', 119 => '0.000000000000000000000000000000000001504632769052528010199982 +7676444744676078919126683', 120 => '0.000000000000000000000000000000000000752316384526264005099991 +38382223723380394595633414', 121 => '0.000000000000000000000000000000000000376158192263132002549995 +69191111861690197297816707', 122 => '0.000000000000000000000000000000000000188079096131566001274997 +84595555930845098648908353', 123 => '0.000000000000000000000000000000000000094039548065783000637498 +922977779654225493244541767', 124 => '0.000000000000000000000000000000000000047019774032891500318749 +461488889827112746622270884', 125 => '0.000000000000000000000000000000000000023509887016445750159374 +730744444913556373311135442', 126 => '0.000000000000000000000000000000000000011754943508222875079687 +365372222456778186655567721', 127 => '0.000000000000000000000000000000000000005877471754111437539843 +6826861112283890933277838604', 128 => '0.000000000000000000000000000000000000002938735877055718769921 +8413430556141945466638919302', 129 => '0.000000000000000000000000000000000000001469367938527859384960 +9206715278070972733319459651', 130 => '0.000000000000000000000000000000000000000734683969263929692480 +46033576390354863666597298255', 131 => '0.000000000000000000000000000000000000000367341984631964846240 +23016788195177431833298649128', 132 => '0.000000000000000000000000000000000000000183670992315982423120 +11508394097588715916649324564', 133 => '0.000000000000000000000000000000000000000091835496157991211560 +057541970487943579583246622819', 134 => '0.000000000000000000000000000000000000000045917748078995605780 +02877098524397178979162331141', 135 => '0.000000000000000000000000000000000000000022958874039497802890 +014385492621985894895811655705', 136 => '0.000000000000000000000000000000000000000011479437019748901445 +007192746310992947447905827852', 137 => '0.000000000000000000000000000000000000000005739718509874450722 +5035963731554964737239529139262', 138 => '0.000000000000000000000000000000000000000002869859254937225361 +2517981865777482368619764569631', 139 => '0.000000000000000000000000000000000000000001434929627468612680 +6258990932888741184309882284816', 140 => '0.000000000000000000000000000000000000000000717464813734306340 +31294954664443705921549411424078', 141 => '0.000000000000000000000000000000000000000000358732406867153170 +15647477332221852960774705712039', 142 => '0.000000000000000000000000000000000000000000179366203433576585 +07823738666110926480387352856019', 143 => '0.000000000000000000000000000000000000000000089683101716788292 +539118693330554632401936764280097', 144 => '0.000000000000000000000000000000000000000000044841550858394146 +269559346665277316200968382140049', 145 => '0.000000000000000000000000000000000000000000022420775429197073 +134779673332638658100484191070024', 146 => '0.000000000000000000000000000000000000000000011210387714598536 +567389836666319329050242095535012', 147 => '0.000000000000000000000000000000000000000000005605193857299268 +2836949183331596645251210477675061', 148 => '0.000000000000000000000000000000000000000000002802596928649634 +141847459166579832262560523883753', 149 => '0.000000000000000000000000000000000000000000001401298464324817 +0709237295832899161312802619418765', 150 => '0.000000000000000000000000000000000000000000000700649232162408 +53546186479164495806564013097093826', 151 => '0.000000000000000000000000000000000000000000000350324616081204 +26773093239582247903282006548546913', 152 => '0.000000000000000000000000000000000000000000000175162308040602 +13386546619791123951641003274273456', 153 => '0.000000000000000000000000000000000000000000000087581154020301 +066932733098955619758205016371367282', 154 => '0.000000000000000000000000000000000000000000000043790577010150 +533466366549477809879102508185683641', 155 => '0.000000000000000000000000000000000000000000000021895288505075 +266733183274738904939551254092841821', 156 => '0.000000000000000000000000000000000000000000000010947644252537 +63336659163736945246977562704642091', 157 => '0.000000000000000000000000000000000000000000000005473822126268 +8166832958186847262348878135232104551', 158 => '0.000000000000000000000000000000000000000000000002736911063134 +4083416479093423631174439067616052276', 159 => '0.000000000000000000000000000000000000000000000001368455531567 +2041708239546711815587219533808026138', ); my $pi = '3.1415926535897932384626433832795'; my ($msd, $lsd) = i2dd($pi, \%bits_table, \%vals_table); print "$msd $lsd\n"; printf "%a %a\n", $msd, $lsd ; sub i2dd { my $str = $_[0]; my $sign = $str =~ s/^\-// ? -1 : 1; my $val = Math::BigFloat->new($str); my $msd = 0 + $val->bstr; my ($bin, $exp) = d2bin($msd, $_[1]); my $to_subtract = bin2val($bin, $_[2]) * (2 ** $exp); $val -= $to_subtract; my $lsd = 0 + $val->bstr; return ($msd * $sign, $lsd * $sign); } sub d2bin { my ($mant, $exp) = split /p/, sprintf("%a", $_[0]); my %bits = %{$_[1]}; $mant =~ s/-?0x//i; my $bin = $mant =~ /^1/ ? 1 : 0; $mant =~ s/.+\.//; for(1 .. length($mant)) { $bin .= $bits{substr($mant, $_ - 1, 1)}; } return ($bin, $exp); } sub bin2val { my $bin = $_[0]; my %vals = %{$_[1]}; my $val = Math::BigFloat->new(0); for(1 .. length($bin)) { $val += Math::BigFloat->new($vals{$_ - 1}) if substr($bin, $_ - 1, + 1); } return $val; } __END__ Outputs: 3.14159265358979 1.22464679914735e-016 0x1.921fb54442d18p+1 0x1.1a62633145c07p-53
        The values in %vals_tab have been calculated to 160 bits of precision. 160 is an arbitrarily chosen value, == 1 + (3 * 53).
        I make no claims about this approach. (I'll scrutinise it and test it over the next week or so.)

        Cheers,
        Rob