2009-02-20 16 views
5

To pytanie jest podobne do "dropping trailing ‘.0’ from floats", ale dla Perla i z maksymalną liczbą cyfr po przecinku.W Perlu, w jaki sposób mogę ograniczyć liczbę miejsc po przecinku, ale bez końcowych zer?

Szukam sposobu na konwersję liczb na format ciągów, upuszczając wszelkie zbędne "0", w tym nie tylko zaraz po przecinku. I wciąż z maksymalną liczbą cyfrowej, np. 3

Dane wejściowe są zmiennoprzecinkowe. Pożądany wyjściowa:

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

Odpowiedz

3

Można również użyć Math::Round to zrobić:

$ 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

Rozwiązanie to działa tylko na małych ilościach. 'print' upuszcza część ułamkową lub przełącza się na notację naukową łącznie po 15 cyfrach; 'najbliższy' może wzmocnić każdy błąd już obecny w numerze (np. zaokrąglenie' 111111111129995.56' do '.001' z' najbliższym' daje '111111111129995.58', podczas gdy' sprintf ("% .3f", 111111111129995.56) 'poprawnie tworzy' 111111111129995.56' .) – vladr

18

Użyj następujących bezpośrednio:

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

print $s 

... lub zdefiniować podprogram zrobić to bardziej ogólnie:

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

Drukuje:

0 
1 
1.1 
1.12 
1.123 
1.123 
1.12 
1.12345 
0

To da ci wyjście, na które patrzysz g dla,

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

Możesz użyć "sprintf" w połączeniu z "eval".

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

Na przykład

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

wyjścia:

0 
1 
1 
0.1 
0.1 
0.11 
0.111 
0.111 
0.111 
Powiązane problemy