Pregunta

¿Cómo puedo redondear un número decimal (punto flotante) al entero más cercano?

por ejemplo

1.2 = 1
1.7 = 2
¿Fue útil?

Solución

Salida de perldoc -q round

¿Tiene Perl una función round ()? ¿Qué pasa con ceil () y floor ()? Funciones de disparo?

Recuerde que int () simplemente trunca hacia 0 . Para redondear a un cierto número de dígitos, sprintf () o printf () suele ser la más fácil ruta.

    printf("%.3f", 3.1415926535);       # prints 3.142

El módulo POSIX (parte de la distribución estándar de Perl) implementa ceil () , floor () , y una serie de otras funciones matemáticas y trigonométricas funciones

    use POSIX;
    $ceil   = ceil(3.5);                        # 4
    $floor  = floor(3.5);                       # 3

En 5.000 a 5.003 perls, la trigonometría se realizó en Math :: Complex módulo. Con 5.004, el módulo Math :: Trig (parte de el perl estandar distribución) implementa las funciones trigonométricas. Internamente utiliza el módulo Math :: Complex y algunas funciones pueden fallar fuera de la Eje real en el plano complejo, por ejemplo, el seno inverso de 2.

El redondeo en aplicaciones financieras puede tener serias implicaciones, y El método de redondeo utilizado debe especificarse con precisión. En estos En algunos casos, probablemente vale la pena no confiar en el redondeo del sistema. utilizado por Perl, pero para implementar la función de redondeo que necesita tú mismo.

Para ver por qué, observe cómo seguirá teniendo un problema en el punto medio alternancia:

    for ($i = 0; $i < 1.01; $i += 0.05) { printf "%.1f ",$i}

    0.0 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.4 0.5 0.5 0.6 0.7 0.7
    0.8 0.8 0.9 0.9 1.0 1.0

No culpes a Perl. Es lo mismo que en C. IEEE dice que tenemos que hacer esta. Los números de Perl cuyos valores absolutos son enteros en 2 ** 31 (en Máquinas de 32 bits) funcionarán de manera muy similar a los enteros matemáticos Otros números no están garantizados.

Otros consejos

Aunque no esté en desacuerdo con las complejas respuestas sobre las marcas a mitad de camino, etc., para el caso de uso más común (y posiblemente trivial):

my $ rounded = int ($ float + 0.5);

ACTUALIZAR

Si es posible que su $ float sea negativo, la siguiente variación producirá el resultado correcto:

my $ rounded = int ($ float + $ float / abs ($ float * 2 || 1));

Con este cálculo, -1.4 se redondea a -1, y -1.6 a -2, y el cero no explotará.

Puedes usar un módulo como Math :: Round :

use Math::Round;
my $rounded = round( $float );

O puedes hacerlo de manera cruda:

my $rounded = sprintf "%.0f", $float;

Si decides usar printf o sprintf, ten en cuenta que usan Redondear la mitad para igualar método.

foreach my $i ( 0.5, 1.5, 2.5, 3.5 ) {
    printf "$i -> %.0f\n", $i;
}
__END__
0.5 -> 0
1.5 -> 2
2.5 -> 2
3.5 -> 4

Consulte perldoc / perlfaq :

  

Recuerde que int () simplemente trunca hacia 0. Para redondear a un   Cierto número de dígitos, sprintf () o printf () suele ser el   Ruta más fácil.

 printf("%.3f",3.1415926535);
 # prints 3.142
     

El módulo POSIX (parte de la distribución Perl estándar)   implementa ceil () , floor () , y una serie de otros   y funciones trigonométricas.

use POSIX;
$ceil  = ceil(3.5); # 4
$floor = floor(3.5); # 3
     

En 5.000 a 5.003 perls, la trigonometría se realizó en el módulo Math :: Complex .

     

Con 5.004, el módulo Math :: Trig (parte de la distribución Perl estándar) > implementa las funciones trigonométricas.

     

Internamente utiliza el módulo Math :: Complex y algunas funciones pueden interrumpirse   desde el eje real al plano complejo, por ejemplo, el seno inverso de 2.

     

El redondeo en las aplicaciones financieras puede tener serias implicaciones, y el redondeo   El método utilizado debe especificarse con precisión. En estos casos, probablemente vale la pena no   confíe en cualquier redondeo del sistema que esté utilizando Perl, pero para implementar el   Función de redondeo que necesita usted mismo.

     

Para ver por qué, observe cómo seguirá teniendo un problema en la alternancia de medio punto:

for ($i = 0; $i < 1.01; $i += 0.05)
{
   printf "%.1f ",$i
}

0.0 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.4 0.5 0.5 0.6 0.7 0.7 0.8 0.8 0.9 0.9 1.0 1.0
     

No culpes a Perl. Es lo mismo que en C. IEEE dice que tenemos que hacer   esta. Los números de Perl cuyos valores absolutos son enteros menores de 2 ** 31 (en   Máquinas de 32 bits) funcionarán de manera muy similar a los enteros matemáticos   Otros números no están garantizados.

No necesitas ningún módulo externo.

$x[0] = 1.2;
$x[1] = 1.7;

foreach (@x){
  print 

No necesitas ningún módulo externo.

<*>

Puede que me esté perdiendo tu punto, pero pensé que esta era una forma mucho más limpia de hacer el mismo trabajo.

Lo que esto hace es recorrer cada número positivo en el elemento, imprimir el número y el entero redondeado en el formato que mencionaste. El código concatena el entero positivo redondeado respectivo solo en función de los decimales. int ($ _) básicamente redondea hacia abajo el número, de modo que ($ -int ($ )) captura los decimales. Si los decimales son (por definición) estrictamente menores a 0.5, redondea el número hacia abajo. Si no, redondea agregando 1.

.' = '.( ( (

No necesitas ningún módulo externo.

<*>

Puede que me esté perdiendo tu punto, pero pensé que esta era una forma mucho más limpia de hacer el mismo trabajo.

Lo que esto hace es recorrer cada número positivo en el elemento, imprimir el número y el entero redondeado en el formato que mencionaste. El código concatena el entero positivo redondeado respectivo solo en función de los decimales. int ($ _) básicamente redondea hacia abajo el número, de modo que ($ -int ($ )) captura los decimales. Si los decimales son (por definición) estrictamente menores a 0.5, redondea el número hacia abajo. Si no, redondea agregando 1.

-int(

No necesitas ningún módulo externo.

<*>

Puede que me esté perdiendo tu punto, pero pensé que esta era una forma mucho más limpia de hacer el mismo trabajo.

Lo que esto hace es recorrer cada número positivo en el elemento, imprimir el número y el entero redondeado en el formato que mencionaste. El código concatena el entero positivo redondeado respectivo solo en función de los decimales. int ($ _) básicamente redondea hacia abajo el número, de modo que ($ -int ($ )) captura los decimales. Si los decimales son (por definición) estrictamente menores a 0.5, redondea el número hacia abajo. Si no, redondea agregando 1.

))<0.5) ? int(

No necesitas ningún módulo externo.

<*>

Puede que me esté perdiendo tu punto, pero pensé que esta era una forma mucho más limpia de hacer el mismo trabajo.

Lo que esto hace es recorrer cada número positivo en el elemento, imprimir el número y el entero redondeado en el formato que mencionaste. El código concatena el entero positivo redondeado respectivo solo en función de los decimales. int ($ _) básicamente redondea hacia abajo el número, de modo que ($ -int ($ )) captura los decimales. Si los decimales son (por definición) estrictamente menores a 0.5, redondea el número hacia abajo. Si no, redondea agregando 1.

) : int(

No necesitas ningún módulo externo.

<*>

Puede que me esté perdiendo tu punto, pero pensé que esta era una forma mucho más limpia de hacer el mismo trabajo.

Lo que esto hace es recorrer cada número positivo en el elemento, imprimir el número y el entero redondeado en el formato que mencionaste. El código concatena el entero positivo redondeado respectivo solo en función de los decimales. int ($ _) básicamente redondea hacia abajo el número, de modo que ($ -int ($ )) captura los decimales. Si los decimales son (por definición) estrictamente menores a 0.5, redondea el número hacia abajo. Si no, redondea agregando 1.

)+1 ); print "\n"; }

Puede que me esté perdiendo tu punto, pero pensé que esta era una forma mucho más limpia de hacer el mismo trabajo.

Lo que esto hace es recorrer cada número positivo en el elemento, imprimir el número y el entero redondeado en el formato que mencionaste. El código concatena el entero positivo redondeado respectivo solo en función de los decimales. int ($ _) básicamente redondea hacia abajo el número, de modo que ($ -int ($ )) captura los decimales. Si los decimales son (por definición) estrictamente menores a 0.5, redondea el número hacia abajo. Si no, redondea agregando 1.

Lo siguiente redondeará los números positivos o negativos a una posición decimal dada:

sub round ()
{
    my ($x, $pow10) = @_;
    my $a = 10 ** $pow10;

    return (int($x / $a + (($x < 0) ? -0.5 : 0.5)) * $a);
}

A continuación se muestra una muestra de cinco formas diferentes de sumar valores. La primera es una forma ingenua de realizar la suma (y falla). El segundo intenta usar sprintf () , pero también falla. El tercero usa sprintf () con éxito, mientras que los dos últimos (4th y amp; 5th) usan floor ($ value + 0.5) .

 use strict;
 use warnings;
 use POSIX;

 my @values = (26.67,62.51,62.51,62.51,68.82,79.39,79.39);
 my $total1 = 0.00;
 my $total2 = 0;
 my $total3 = 0;
 my $total4 = 0.00;
 my $total5 = 0;
 my $value1;
 my $value2;
 my $value3;
 my $value4;
 my $value5;

 foreach $value1 (@values)
 {
      $value2 = $value1;
      $value3 = $value1;
      $value4 = $value1;
      $value5 = $value1;

      $total1 += $value1;

      $total2 += sprintf('%d', $value2 * 100);

      $value3 = sprintf('%1.2f', $value3);
      $value3 =~ s/\.//;
      $total3 += $value3;

      $total4 += $value4;

      $total5 += floor(($value5 * 100.0) + 0.5);
 }

 $total1 *= 100;
 $total4 = floor(($total4 * 100.0) + 0.5);

 print '$total1: '.sprintf('%011d', $total1)."\n";
 print '$total2: '.sprintf('%011d', $total2)."\n";
 print '$total3: '.sprintf('%011d', $total3)."\n";
 print '$total4: '.sprintf('%011d', $total4)."\n";
 print '$total5: '.sprintf('%011d', $total5)."\n";

 exit(0);

 #$total1: 00000044179
 #$total2: 00000044179
 #$total3: 00000044180
 #$total4: 00000044180
 #$total5: 00000044180

Tenga en cuenta que floor ($ value + 0.5) se puede reemplazar con int ($ value + 0.5) para eliminar la dependencia en POSIX .

Los números negativos pueden agregar algunas peculiaridades que las personas deben tener en cuenta.

Los enfoques de estilo

printf nos dan números correctos, pero pueden dar como resultado algunas visualizaciones impares. Hemos descubierto que este método (en mi opinión, estúpidamente) coloca en un signo - si debería o no debería o no. Por ejemplo, -0.01 redondeado a un lugar decimal devuelve un -0.0, en lugar de solo 0. Si va a hacer el enfoque de estilo printf , y sabe que no quiere un decimal, use % d y no % f (cuando necesitas decimales, es cuando la pantalla se pone borrosa).

Si bien es correcto y para las matemáticas no es gran cosa, para mostrarlo solo se ve raro mostrando algo como " -0.0 " ;.

Para el método int, los números negativos pueden cambiar lo que quieres como resultado (aunque hay algunos argumentos que pueden ser correctos).

El int + 0.5 causa problemas reales con los números negativos, a menos que quieras que funcione de esa manera, pero imagino que la mayoría de las personas no lo hacen. -0.9 probablemente debería redondear a -1, no a 0. Si sabe que quiere que el negativo sea un techo en lugar de un piso, entonces puede hacerlo en una sola línea, de lo contrario, puede usar el método int con un menor modificación (esto obviamente solo funciona para recuperar números enteros:

my $var = -9.1;
my $tmpRounded = int( abs($var) + 0.5));
my $finalRounded = $var >= 0 ? 0 + $tmpRounded : 0 - $tmpRounded;

Mi solución para sprintf

if ($value =~ m/\d\..*5$/){
    $format =~ /.*(\d)f$/;
    if (defined $1){
       my $coef = "0." . "0" x $1 . "05";    
            $value = $value + $coef;    
    }
}

$value = sprintf( "$format", $value );

Si solo le interesa obtener un valor entero de un número de punto flotante completo (es decir, 12347.9999 o 54321.0001), este enfoque (tomado en préstamo y modificado desde arriba) hará el truco:

my $rounded = floor($float + 0.1); 
cat table |
  perl -ne '/\d+\s+(\d+)\s+(\S+)/ && print "".**int**(log($1)/log(2))."\t$2\n";' 
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top