Reputation: 37146
Consider the following float:
8.22120183514065e-05
Now obviously (s)printf
is the standard thing to do here, but %f
alters its precision:
printf "%f", 8.22120183514065e-05; # 0.000082
Using an arbitrarily large precision, say %.30f
, adds additional digits (...6505
):
printf "%.30f", 8.22120183514065e-05; # 0.000082212081351406505000000000
Is there a way to maintain the precision present in the scientific notation without knowing its exact precision in advance?
Upvotes: 2
Views: 82
Reputation: 385809
I believe you are asking how to stringify a number such that the stringification has the same number of signficant digits as the code literal that produced the number.
That's impossible. The number of significant digits in the code literal that produced the number (if there even was such a literal) is not stored anywhere.
Simply put, there's no way to get
0.0000822120183514065
or even
8.22120183514065e-05
from the number
0.0000822120183514065132508730204818903075647540390491485595703125
from the available information.
It would be different if you started with the string
8.22120183514065e-05
or if you knew the desired precision such that you could create the above string using
sprintf('%.*e', $significant_digits-1, $n)
If you had this, you could perform string manipulations to move the .
as needed.
$n =~ s/^\d\K\.// ? $n =~ s/^\d+\Ke([+-]\d+)\z// : $n =~ s/^\d\Ke([+-]\d+)\z// or die;
my $exp = $1 + 1;
if ( $exp <= 0 ) { $n = '0.' . ( '0' x -$exp ) . $n; }
elsif ( $exp < length($n) ) { substr($n, $exp, 0, '.'); }
elsif ( $exp > length($n) ) { $n .= '0' x ( $exp - length($n) ); }
$ perl -e'printf "%.70f\n", 8.22120183514065e-05;'
0.0000822120183514065132508730204818903075647540390491485595703125000000
$ perl -e'printf "%.70e\n", 8.22120183514065e-05;'
8.2212018351406513250873020481890307564754039049148559570312500000000000e-05
$ perl -e'printf "%.*e\n", 14, 8.22120183514065e-05;'
8.22120183514065e-05
Upvotes: 3