2009-02-20 7 views
5

Questa domanda è simile a "dropping trailing ‘.0’ from floats", ma per Perl e con un numero massimo di cifre dopo il decimale.In Perl, come posso limitare il numero di posti dopo il punto decimale ma non avere zero finali?

Sto cercando un modo per convertire i numeri in formato stringa, eliminando qualsiasi "0" ridondante, incluso non appena dopo il decimale. E ancora con un numero massimo di digitali, ad es. 3

I dati di input sono float. output desiderato:

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

risposta

3

È inoltre possibile utilizzare Math::Round per fare questo:

$ 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

Questa soluzione funziona solo per piccole quantità. 'print' rilascia la parte frazionaria o passa alla notazione scientifica del tutto dopo 15 cifre; 'nearest' può amplificare qualsiasi errore già presente nel numero (ad esempio arrotondare' 111111111129995.56' a '.001' con' nearest' produce '111111111129995.58', mentre' sprintf ("%. 3f", 11111111129995.56) 'produce correttamente' 1111111112129595,56' .) – vladr

18

Utilizzare la seguente direttamente:

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

print $s 

... o definire una subroutine per farlo più genericamente:

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"; 

stampe:

0 
1 
1.1 
1.12 
1.123 
1.123 
1.12 
1.12345 
0

Questo ti darà l'output che stai cercando g per,

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

È possibile utilizzare "sprintf" combinato con "eval".

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

Ad esempio:

#!/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"; 
} 

uscite:

0 
1 
1 
0.1 
0.1 
0.11 
0.111 
0.111 
0.111