Question

Comment puis-je arrondir un nombre décimal (virgule flottante) au nombre entier le plus proche?

par exemple

1.2 = 1
1.7 = 2
Était-ce utile?

La solution

Résultat de perldoc -q round

Est-ce que Perl a une fonction round ()? Qu'en est-il de ceil () et de floor ()? Fonctions Trig?

N'oubliez pas que int () ne fait que tronquer vers 0 . Pour arrondir à un certain nombre de chiffres, sprintf () ou printf () est généralement le plus simple. route.

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

Le module POSIX (qui fait partie de la distribution Perl standard) implémente ceil () , floor () et un certain nombre d'autres éléments mathématiques et trigonométriques les fonctions.

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

La trigonométrie a été effectuée dans les Math :: Complex <5.000 à 5.003 perls / a> module. Avec 5.004, le module Math :: Trig (qui fait partie de le standard Perl distribution) implémente les fonctions trigonométriques. Intérieurement utilise le module Math :: Complex et certaines fonctions peuvent échouer hors du axe réel dans le plan complexe, par exemple le sinus inverse de 2.

Arrondir les applications financières peut avoir de graves conséquences, et la méthode d'arrondissement utilisée doit être spécifiée avec précision. Dans ces Dans certains cas, il est probablement préférable de ne pas faire confiance à l’arrondi système. utilisé par Perl, mais pour implémenter la fonction d'arrondi dont vous avez besoin toi même.

Pour voir pourquoi, remarquez que vous aurez toujours un problème à mi-chemin. alternance:

    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

Ne blâmez pas Perl. C'est la même chose que dans C. IEEE dit qu'il faut faire ce. Les nombres Perl dont les valeurs absolues sont des entiers sous 2 ** 31 (le Machines 32 bits) fonctionneront plus ou moins comme des entiers mathématiques. Les autres numéros ne sont pas garantis.

Autres conseils

Même si vous n'êtes pas en désaccord avec les réponses complexes concernant les demi-marques, etc., pour le cas d'utilisation le plus courant (et peut-être trivial):

mon $ arrondi = int ($ float + 0.5);

MISE À JOUR

S'il est possible que votre $ float soit négatif, la variante suivante produira le résultat correct:

mon $ arrondi = int ($ float + $ float / abs ($ float * 2 || 1));

Avec ce calcul, -1.4 est arrondi à -1, et -1.6 à -2 et le zéro n’explosera pas.

Vous pouvez utiliser un module tel que Math :: Round :

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

Ou vous pouvez le faire grossièrement:

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

Si vous décidez d'utiliser printf ou sprintf, notez qu'ils utilisent Arrondir à moitié selon la méthode.

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

Voir perldoc / perlfaq :

  

N'oubliez pas que int () ne fait que tronquer vers 0. Pour arrondir à un   nombre de chiffres, sprintf () ou printf () est généralement le   itinéraire le plus facile.

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

Le module POSIX (élément de la distribution Perl standard)   implémente ceil () , floor () et un certain nombre d'autres éléments mathématiques   et fonctions trigonométriques.

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

En 5.000 à 5.003 perls, la trigonométrie a été effectuée dans le module Math :: Complex .

     

Avec 5.004, le module Math :: Trig (élément de la distribution Perl standard) > implémente les fonctions trigonométriques.

     

En interne, il utilise le module Math :: Complex et certaines fonctions peuvent ne plus fonctionner.   hors de l’axe réel dans le plan complexe, par exemple le sinus inverse de 2.

     

Arrondir les applications financières peut avoir de graves conséquences, et l’arrondi   La méthode utilisée doit être spécifiée avec précision. Dans ces cas, il vaut probablement mieux ne pas   confiance, quel que soit l'arrondi système utilisé par Perl, mais pour mettre en œuvre le   fonction d'arrondissement dont vous avez besoin vous-même.

     

Pour savoir pourquoi, remarquez que vous aurez toujours un problème d'alternance à mi-parcours:

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
     

Ne blâmez pas Perl. C'est la même chose que dans C. IEEE dit qu'il faut faire   ce. Les nombres Perl dont les valeurs absolues sont des entiers inférieurs à 2 ** 31 (le   Machines 32 bits) fonctionneront plus ou moins comme des entiers mathématiques.   Les autres numéros ne sont pas garantis.

Vous n'avez besoin d'aucun module externe.

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

foreach (@x){
  print 

Vous n'avez besoin d'aucun module externe.

<*>

Je comprends peut-être votre argument, mais j’ai pensé que c’était une façon beaucoup plus propre de faire le même travail.

Cela permet de parcourir chaque nombre positif dans l'élément, d'imprimer le nombre et l'entier arrondi dans le format que vous avez mentionné. Le code concatène le nombre entier positif arrondi respectif uniquement en fonction des décimales. int ($ _), fondamentalement arrondi le nombre afin que ($ -int ($ )) capture les décimales. Si les décimales sont (par définition) strictement inférieures à 0,5, arrondissez le nombre. Sinon, arrondissez en ajoutant 1.

.' = '.( ( (

Vous n'avez besoin d'aucun module externe.

<*>

Je comprends peut-être votre argument, mais j’ai pensé que c’était une façon beaucoup plus propre de faire le même travail.

Cela permet de parcourir chaque nombre positif dans l'élément, d'imprimer le nombre et l'entier arrondi dans le format que vous avez mentionné. Le code concatène le nombre entier positif arrondi respectif uniquement en fonction des décimales. int ($ _), fondamentalement arrondi le nombre afin que ($ -int ($ )) capture les décimales. Si les décimales sont (par définition) strictement inférieures à 0,5, arrondissez le nombre. Sinon, arrondissez en ajoutant 1.

-int(

Vous n'avez besoin d'aucun module externe.

<*>

Je comprends peut-être votre argument, mais j’ai pensé que c’était une façon beaucoup plus propre de faire le même travail.

Cela permet de parcourir chaque nombre positif dans l'élément, d'imprimer le nombre et l'entier arrondi dans le format que vous avez mentionné. Le code concatène le nombre entier positif arrondi respectif uniquement en fonction des décimales. int ($ _), fondamentalement arrondi le nombre afin que ($ -int ($ )) capture les décimales. Si les décimales sont (par définition) strictement inférieures à 0,5, arrondissez le nombre. Sinon, arrondissez en ajoutant 1.

))<0.5) ? int(

Vous n'avez besoin d'aucun module externe.

<*>

Je comprends peut-être votre argument, mais j’ai pensé que c’était une façon beaucoup plus propre de faire le même travail.

Cela permet de parcourir chaque nombre positif dans l'élément, d'imprimer le nombre et l'entier arrondi dans le format que vous avez mentionné. Le code concatène le nombre entier positif arrondi respectif uniquement en fonction des décimales. int ($ _), fondamentalement arrondi le nombre afin que ($ -int ($ )) capture les décimales. Si les décimales sont (par définition) strictement inférieures à 0,5, arrondissez le nombre. Sinon, arrondissez en ajoutant 1.

) : int(

Vous n'avez besoin d'aucun module externe.

<*>

Je comprends peut-être votre argument, mais j’ai pensé que c’était une façon beaucoup plus propre de faire le même travail.

Cela permet de parcourir chaque nombre positif dans l'élément, d'imprimer le nombre et l'entier arrondi dans le format que vous avez mentionné. Le code concatène le nombre entier positif arrondi respectif uniquement en fonction des décimales. int ($ _), fondamentalement arrondi le nombre afin que ($ -int ($ )) capture les décimales. Si les décimales sont (par définition) strictement inférieures à 0,5, arrondissez le nombre. Sinon, arrondissez en ajoutant 1.

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

Je comprends peut-être votre argument, mais j’ai pensé que c’était une façon beaucoup plus propre de faire le même travail.

Cela permet de parcourir chaque nombre positif dans l'élément, d'imprimer le nombre et l'entier arrondi dans le format que vous avez mentionné. Le code concatène le nombre entier positif arrondi respectif uniquement en fonction des décimales. int ($ _), fondamentalement arrondi le nombre afin que ($ -int ($ )) capture les décimales. Si les décimales sont (par définition) strictement inférieures à 0,5, arrondissez le nombre. Sinon, arrondissez en ajoutant 1.

Les éléments suivants arrondissent les nombres positifs ou négatifs à une position décimale donnée:

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

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

Vous trouverez ci-dessous un échantillon de cinq façons différentes de additionner des valeurs. Le premier est un moyen naïf d’effectuer la sommation (et échoue). La seconde tente d’utiliser sprintf () , mais elle échoue aussi. Le troisième utilise sprintf () avec succès, tandis que les deux derniers (4ème et 5ème) utilisent étage ($ valeur + 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

Notez que floor ($ valeur + 0.5) peut être remplacé par int ($ valeur + 0.5) pour supprimer la dépendance à POSIX . .

Les nombres négatifs peuvent ajouter certaines bizarreries que les gens doivent connaître.

Les approches de style

printf nous donnent les bons numéros, mais ils peuvent donner des affichages bizarres. Nous avons découvert que cette méthode (à mon avis, stupidement) place dans un signe - si elle devrait ou non. Par exemple, -0,01 arrondi à une décimale renvoie -0,0, plutôt que 0. Si vous allez utiliser l'approche de style printf et que vous savez que vous ne voulez pas de décimale, utilisez . % d et pas % f (lorsque vous avez besoin de décimales, c'est lorsque l'affichage devient confus).

Bien que ce soit correct et pour les mathématiques, ce n’est pas grave, mais pour l’affichage, cela donne une apparence bizarre montrant quelque chose comme "-0.0".

Pour la méthode int, les nombres négatifs peuvent changer le résultat souhaité (bien que certains arguments puissent être définis, ils sont corrects).

Le int + 0.5 pose de vrais problèmes avec les nombres négatifs, à moins que vous ne vouliez que cela fonctionne ainsi, mais j'imagine que la plupart des gens ne le font pas. -0,9 devrait probablement arrondir à -1 et non pas 0. Si vous savez que vous voulez que le négatif soit un plafond plutôt qu'un sol, vous pouvez le faire en une ligne, sinon, vous pouvez utiliser la méthode int avec un mineur modification (cela ne fonctionne évidemment que pour récupérer des nombres entiers:

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

Ma solution pour 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 vous souhaitez uniquement obtenir une valeur entière dans un nombre entier à virgule flottante (c'est-à-dire 12347.9999 ou 54321.0001), cette approche (empruntée et modifiée ci-dessus) fera l'affaire:

my $rounded = floor($float + 0.1); 
cat table |
  perl -ne '/\d+\s+(\d+)\s+(\S+)/ && print "".**int**(log($1)/log(2))."\t$2\n";' 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top