2009-02-20 13 views
5

Esta pregunta es similar a "dropping trailing ‘.0’ from floats", pero para Perl y con un número máximo de dígitos después del decimal.En Perl, ¿cómo puedo limitar el número de lugares después del punto decimal pero no tener ceros finales?

Estoy buscando una forma de convertir números a formato de cadena, eliminando cualquier '0' redundante, incluso no justo después del decimal. Y aún con un número máximo de digitales, p. 3

Los datos de entrada son flotantes. salida deseada:

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

Respuesta

3

También puede utilizar Math::Round para hacer esto:

$ 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

Esta solución sólo funciona para los números pequeños. 'print' elimina la parte fraccionaria o cambia a notación científica por completo después de 15 dígitos; 'más cercano' puede amplificar cualquier error ya presente en el número (ej. redondeando' 111111111129995.56' a '.001' con' más cercano' produce '111111111129995.58', mientras' sprintf ("%. 3f", 111111111129995.56) 'produce correctamente' 111111111129995.56' .) – vladr

18

directamente en Usar la siguiente:

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

print $s 

... o definir una subrutina para hacerlo más genéricamente:

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

Lienzo:

0 
1 
1.1 
1.12 
1.123 
1.123 
1.12 
1.12345 
0

Esto le dará la salida de su lookin g para,

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

Puede utilizar "sprintf" combinada con "eval".

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

Por ejemplo:

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

salidas:

0 
1 
1 
0.1 
0.1 
0.11 
0.111 
0.111 
0.111 
Cuestiones relacionadas