2009-02-20 8 views
5

Cette question est similaire à "dropping trailing ‘.0’ from floats", mais pour Perl et avec un nombre maximum de chiffres après la virgule.En Perl, comment puis-je limiter le nombre de places après la virgule mais sans zéros de fin?

Je suis à la recherche d'un moyen de convertir les nombres au format de chaîne, en supprimant tout '0' redondant, y compris pas juste après la décimale. Et toujours avec un maximum de numérique, par ex. 3

Les données d'entrée sont flottantes. sortie souhaitée:

0   -> 0 
0.1  -> 0.1 
0.11  -> 0.11 
0.111  -> 0.111 
0.1111111 -> 0.111 

Répondre

3

Vous pouvez également utiliser Math::Round pour ce faire:

$ perl -MMath::Round=nearest -e 'print nearest(.001, 0.1), "\n"' 
0.1 
$ perl -MMath::Round=nearest -e 'print nearest(.001, 0.11111), "\n"' 
0.111 
+1

Cette solution ne fonctionne que pour un petit nombre. 'print' laisse tomber la partie fractionnaire ou passe à la notation scientifique complètement après 15 chiffres; 'nearest nearest 'peut amplifier toute erreur déjà présente dans le nombre (par exemple arrondir' 111111111129995.56' à' .001' avec 'nearest' produit' 111111111129995.58', alors que 'sprintf ("%. 3f ", 111111111129995.56)' produit correctement '111111111129995.56' .) – vladr

18

Utilisez les éléments suivants directement:

my $s = sprintf('%.3f', $f); 
$s =~ s/\.?0*$//; 

print $s 

... ou définir un sous-programme pour le faire de manière plus générique:

sub fstr { 
    my ($value,$precision) = @_; 
    $precision ||= 3; 
    my $s = sprintf("%.${precision}f", $value); 
    $s =~ s/\.?0*$//; 
    $s 
} 

print fstr(0) . "\n"; 
print fstr(1) . "\n"; 
print fstr(1.1) . "\n"; 
print fstr(1.12) . "\n"; 
print fstr(1.123) . "\n"; 
print fstr(1.12345) . "\n"; 
print fstr(1.12345, 2) . "\n"; 
print fstr(1.12345, 10) . "\n"; 

Prints:

0 
1 
1.1 
1.12 
1.123 
1.123 
1.12 
1.12345 
0

Cela vous donnera la sortie de votre lookin g pour,

sub dropTraillingZeros{ 
$_ = shift; 
s/(\d*\.\d{3})(.*)/$1/; 
s/(\d*\.\d)(00)/$1/; 
s/(\d*\.\d{2})(0)/$1/; 
print "$_\n"; 
} 
dropTraillingZeros(0); 
dropTraillingZeros(0.1); 
dropTraillingZeros(0.11); 
dropTraillingZeros(0.111); 
dropTraillingZeros(0.11111111); 
2

Vous pouvez utiliser "sprintf" combiné avec "eval".

my $num = eval sprintf('%.3f', $raw_num); 

Par exemple:

#!/usr/bin/perl 

my @num_array = (
    0, 1, 1.0, 0.1, 0.10, 0.11, 0.111, 0.1110, 0.1111111 
); 


for my $raw_num (@num_array) { 
    my $num = eval sprintf('%.3f', $raw_num); 
    print $num . "\n"; 
} 

sorties:

0 
1 
1 
0.1 
0.1 
0.11 
0.111 
0.111 
0.111 
Questions connexes