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.00000000000000000021684043449710088680149056017398834228515625', 63 => '0.000000000000000000108420217248550443400745280086994171142578125', 64 => '0.0000000000000000000542101086242752217003726400434970855712890625', 65 => '0.00000000000000000002710505431213761085018632002174854278564453125', 66 => '0.000000000000000000013552527156068805425093160010874271392822265625', 67 => '0.0000000000000000000067762635780344027125465800054371356964111328125', 68 => '0.00000000000000000000338813178901720135627329000271856784820556640625', 69 => '0.000000000000000000001694065894508600678136645001359283924102783203125', 70 => '0.0000000000000000000008470329472543003390683225006796419620513916015625', 71 => '0.00000000000000000000042351647362715016953416125033982098102569580078125', 72 => '0.00000000000000000000021175823681357508476708062516991049051284790039062', 73 => '0.00000000000000000000010587911840678754238354031258495524525642395019531', 74 => '0.000000000000000000000052939559203393771191770156292477622628211975097656', 75 => '0.000000000000000000000026469779601696885595885078146238811314105987548828', 76 => '0.000000000000000000000013234889800848442797942539073119405657052993774414', 77 => '0.000000000000000000000006617444900424221398971269536559702828526496887207', 78 => '0.0000000000000000000000033087224502121106994856347682798514142632484436035', 79 => '0.0000000000000000000000016543612251060553497428173841399257071316242218018', 80 => '0.00000000000000000000000082718061255302767487140869206996285356581211090088', 81 => '0.00000000000000000000000041359030627651383743570434603498142678290605545044', 82 => '0.00000000000000000000000020679515313825691871785217301749071339145302772522', 83 => '0.00000000000000000000000010339757656912845935892608650874535669572651386261', 84 => '0.000000000000000000000000051698788284564229679463043254372678347863256931305', 85 => '0.000000000000000000000000025849394142282114839731521627186339173931628465652', 86 => '0.000000000000000000000000012924697071141057419865760813593169586965814232826', 87 => '0.0000000000000000000000000064623485355705287099328804067965847934829071164131', 88 => '0.0000000000000000000000000032311742677852643549664402033982923967414535582066', 89 => '0.0000000000000000000000000016155871338926321774832201016991461983707267791033', 90 => '0.00000000000000000000000000080779356694631608874161005084957309918536338955164', 91 => '0.00000000000000000000000000040389678347315804437080502542478654959268169477582', 92 => '0.00000000000000000000000000020194839173657902218540251271239327479634084738791', 93 => '0.00000000000000000000000000010097419586828951109270125635619663739817042369395', 94 => '0.000000000000000000000000000050487097934144755546350628178098318699085211846977', 95 => '0.000000000000000000000000000025243548967072377773175314089049159349542605923489', 96 => '0.000000000000000000000000000012621774483536188886587657044524579674771302961744', 97 => '0.0000000000000000000000000000063108872417680944432938285222622898373856514808722', 98 => '0.0000000000000000000000000000031554436208840472216469142611311449186928257404361', 99 => '0.000000000000000000000000000001577721810442023610823457130565572459346412870218', 100 => '0.00000000000000000000000000000078886090522101180541172856528278622967320643510902', 101 => '0.00000000000000000000000000000039443045261050590270586428264139311483660321755451', 102 => '0.00000000000000000000000000000019721522630525295135293214132069655741830160877726', 103 => '0.000000000000000000000000000000098607613152626475676466070660348278709150804388628', 104 => '0.000000000000000000000000000000049303806576313237838233035330174139354575402194314', 105 => '0.000000000000000000000000000000024651903288156618919116517665087069677287701097157', 106 => '0.000000000000000000000000000000012325951644078309459558258832543534838643850548578', 107 => '0.0000000000000000000000000000000061629758220391547297791294162717674193219252742892', 108 => '0.0000000000000000000000000000000030814879110195773648895647081358837096609626371446', 109 => '0.0000000000000000000000000000000015407439555097886824447823540679418548304813185723', 110 => '0.00000000000000000000000000000000077037197775489434122239117703397092741524065928616', 111 => '0.00000000000000000000000000000000038518598887744717061119558851698546370762032964308', 112 => '0.00000000000000000000000000000000019259299443872358530559779425849273185381016482154', 113 => '0.000000000000000000000000000000000096296497219361792652798897129246365926905082410769', 114 => '0.000000000000000000000000000000000048148248609680896326399448564623182963452541205385', 115 => '0.000000000000000000000000000000000024074124304840448163199724282311591481726270602692', 116 => '0.000000000000000000000000000000000012037062152420224081599862141155795740863135301346', 117 => '0.0000000000000000000000000000000000060185310762101120407999310705778978704315676506731', 118 => '0.0000000000000000000000000000000000030092655381050560203999655352889489352157838253365', 119 => '0.0000000000000000000000000000000000015046327690525280101999827676444744676078919126683', 120 => '0.00000000000000000000000000000000000075231638452626400509999138382223723380394595633414', 121 => '0.00000000000000000000000000000000000037615819226313200254999569191111861690197297816707', 122 => '0.00000000000000000000000000000000000018807909613156600127499784595555930845098648908353', 123 => '0.000000000000000000000000000000000000094039548065783000637498922977779654225493244541767', 124 => '0.000000000000000000000000000000000000047019774032891500318749461488889827112746622270884', 125 => '0.000000000000000000000000000000000000023509887016445750159374730744444913556373311135442', 126 => '0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567721', 127 => '0.0000000000000000000000000000000000000058774717541114375398436826861112283890933277838604', 128 => '0.0000000000000000000000000000000000000029387358770557187699218413430556141945466638919302', 129 => '0.0000000000000000000000000000000000000014693679385278593849609206715278070972733319459651', 130 => '0.00000000000000000000000000000000000000073468396926392969248046033576390354863666597298255', 131 => '0.00000000000000000000000000000000000000036734198463196484624023016788195177431833298649128', 132 => '0.00000000000000000000000000000000000000018367099231598242312011508394097588715916649324564', 133 => '0.000000000000000000000000000000000000000091835496157991211560057541970487943579583246622819', 134 => '0.00000000000000000000000000000000000000004591774807899560578002877098524397178979162331141', 135 => '0.000000000000000000000000000000000000000022958874039497802890014385492621985894895811655705', 136 => '0.000000000000000000000000000000000000000011479437019748901445007192746310992947447905827852', 137 => '0.0000000000000000000000000000000000000000057397185098744507225035963731554964737239529139262', 138 => '0.0000000000000000000000000000000000000000028698592549372253612517981865777482368619764569631', 139 => '0.0000000000000000000000000000000000000000014349296274686126806258990932888741184309882284816', 140 => '0.00000000000000000000000000000000000000000071746481373430634031294954664443705921549411424078', 141 => '0.00000000000000000000000000000000000000000035873240686715317015647477332221852960774705712039', 142 => '0.00000000000000000000000000000000000000000017936620343357658507823738666110926480387352856019', 143 => '0.000000000000000000000000000000000000000000089683101716788292539118693330554632401936764280097', 144 => '0.000000000000000000000000000000000000000000044841550858394146269559346665277316200968382140049', 145 => '0.000000000000000000000000000000000000000000022420775429197073134779673332638658100484191070024', 146 => '0.000000000000000000000000000000000000000000011210387714598536567389836666319329050242095535012', 147 => '0.0000000000000000000000000000000000000000000056051938572992682836949183331596645251210477675061', 148 => '0.000000000000000000000000000000000000000000002802596928649634141847459166579832262560523883753', 149 => '0.0000000000000000000000000000000000000000000014012984643248170709237295832899161312802619418765', 150 => '0.00000000000000000000000000000000000000000000070064923216240853546186479164495806564013097093826', 151 => '0.00000000000000000000000000000000000000000000035032461608120426773093239582247903282006548546913', 152 => '0.00000000000000000000000000000000000000000000017516230804060213386546619791123951641003274273456', 153 => '0.000000000000000000000000000000000000000000000087581154020301066932733098955619758205016371367282', 154 => '0.000000000000000000000000000000000000000000000043790577010150533466366549477809879102508185683641', 155 => '0.000000000000000000000000000000000000000000000021895288505075266733183274738904939551254092841821', 156 => '0.00000000000000000000000000000000000000000000001094764425253763336659163736945246977562704642091', 157 => '0.0000000000000000000000000000000000000000000000054738221262688166832958186847262348878135232104551', 158 => '0.0000000000000000000000000000000000000000000000027369110631344083416479093423631174439067616052276', 159 => '0.0000000000000000000000000000000000000000000000013684555315672041708239546711815587219533808026138', ); 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