Also, you've stretched the requested precision to 17 decimal digits, which might be a contributing factor
After anonymonks post above about printf inventing stuff, I explored the possibility, and from what I can tell, if you ask printf for more precision than is available, it just pads with trailing zeros:
printf "dp:%u : %35.*f\n", $_, $_, 3.1415926535897932384626433832795 f
+or 14 .. 20;;
dp:14 : 3.14159265358979
dp:15 : 3.141592653589793
dp:16 : 3.1415926535897931
dp:17 : 3.14159265358979310
dp:18 : 3.141592653589793100
dp:19 : 3.1415926535897931000
dp:20 : 3.14159265358979310000
And: [0] Perl> printf "dp:%u : %.*f\n", $_, $_, 123e-308 for 300 .. 320;;
dp:300 : 0.000 {300 zeros ellided} 000000000000
dp:301 : 0.000 {300 zeros ellided} 0000000000000
dp:302 : 0.000 {300 zeros ellided} 00000000000000
dp:303 : 0.000 {300 zeros ellided} 000000000000000
dp:304 : 0.000 {300 zeros ellided} 0000000000000000
dp:305 : 0.000 {300 zeros ellided} 00000000000000000
dp:306 : 0.000 {300 zeros ellided} 000000000000000001
dp:307 : 0.000 {300 zeros ellided} 0000000000000000012
dp:308 : 0.000 {300 zeros ellided} 00000000000000000123
dp:309 : 0.000 {300 zeros ellided} 000000000000000001230
dp:310 : 0.000 {300 zeros ellided} 0000000000000000012300
dp:311 : 0.000 {300 zeros ellided} 00000000000000000123000
dp:312 : 0.000 {300 zeros ellided} 000000000000000001230000
dp:313 : 0.000 {300 zeros ellided} 0000000000000000012300000
dp:314 : 0.000 {300 zeros ellided} 00000000000000000123000000
dp:315 : 0.000 {300 zeros ellided} 000000000000000001230000000
dp:316 : 0.000 {300 zeros ellided} 0000000000000000012300000000
dp:317 : 0.000 {300 zeros ellided} 00000000000000000123000000000
dp:318 : 0.000 {300 zeros ellided} 000000000000000001230000000000
dp:319 : 0.000 {300 zeros ellided} 0000000000000000012300000000000
dp:320 : 0.000 {300 zeros ellided} 00000000000000000123000000000000
If you want reliable rounding and accuracy with floating point values, use Math::MPFR.
I was actually hoping for simple truncation. I'm only using Math::BigFloat in an attempt to verify my double-double implementation.
And what I've realised/discovered is that the mistake is when M::BF translates the double value when performing the subtraction above.
If I do the translation myself, I get sensible numbers: use Math::BigFloat;;
$n = Math::BigFloat->new( '3.1415926535897932384626433832795' );;
$d = 0 + $n->bstr;;
printf "%.17f\n", $d;;
3.14159265358979310
$bfd = Math::BigFloat->new( sprintf "%.17f", $d );;
print $bfd;;
3.1415926535897931
$n -= $bfd;;
print $n;;
0.0000000000000001384626433832795
Which gives me: 3.14159265358979310
+ 0.0000000000000001384626433832795
= 3.1415926535897932384626433832795 == 3.141592653589793238462643383
+2795 (the input)
And that's all I was after.
|