186 votes

Comment arrondir un nombre à virgule flottante en Perl ?

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

par exemple

1.2 = 1
1.7 = 2

207voto

Vinko Vrsalovic Points 116138

Sortie de perldoc -q round-function%3f--What-about-ceil()-and-floor()%3f--Trig-functions%3f)

Perl dispose-t-il d'une fonction round() ? Qu'en est-il de ceil() et floor() ? Des fonctions de trigonométrie ?

Rappelez-vous que int() est simplement tronqué vers 0 . Pour arrondir à un certain nombre de chiffres, sprintf() ou printf() est généralement le plus facile route.

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

Le site POSIX (qui fait partie de la distribution standard de Perl) met en œuvre le module ceil() , floor() et un certain nombre d'autres fonctions mathématiques et trigonométriques. trigonométriques.

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

Dans les perles 5.000 à 5.003, la trigonométrie a été faite dans les Math::Complex module. Avec la version 5.004, le Math::Trig (qui fait partie de la distribution standard de Perl standard) implémente les fonctions trigonométriques. En interne, il utilise les Math::Complex et certaines fonctions peuvent sortir de l'axe réel l'axe réel dans le plan complexe, par exemple le sinus inverse de 2.

L'arrondi dans les applications financières peut avoir de sérieuses implications, et la méthode d'arrondi utilisée doit être spécifiée avec précision. Dans ces cas Dans ces cas, il est probablement utile de ne pas faire confiance à l'arrondi du système utilisé par Perl, mais d'implémenter vous-même la fonction d'arrondi dont vous avez besoin. vous-même.

Pour comprendre pourquoi, remarquez que vous aurez toujours un problème à mi-chemin. l'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 qu'en C. IEEE dit que nous devons faire cela. Les nombres Perl dont les valeurs absolues sont des entiers sous 2**31 (sur 32 bits) fonctionneront à peu près comme des entiers mathématiques. Les autres nombres ne sont pas garantis.

17 votes

Thariama, pourquoi ceil serait-il déprécié ? Il n'est pas déprécié dans POSIX ou perl pour autant que je sache. Citation nécessaire !

4 votes

@Débutants, n'essayez pas d'utiliser printf si vous voulez le résultat dans une variable, utilisez sprintf ... j'espère que cela vous fera gagner du temps de débogage :-P

0 votes

Puis-je utiliser int() sur les PDL ?

149voto

RET Points 6044

Bien que je ne sois pas en désaccord avec les réponses complexes sur les notes à mi-chemin et ainsi de suite, pour le cas d'utilisation le plus commun (et peut-être trivial) :

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

UPDATE

Si c'est possible pour votre $float pour être négatif, la variation suivante produira le résultat correct :

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

Avec ce calcul, -1,4 est arrondi à -1, et -1,6 à -2, et le zéro n'explose pas.

4 votes

... mais il échoue sur les nombres négatifs : toujours mieux sprintf

2 votes

Ah non, ce n'est pas le cas. Arrondir un nombre négatif vous rapproche de zéro, pas vous en éloigne. Qu'est-ce qu'ils enseignent dans les écoles de nos jours ?

6 votes

@RET Oui, cela échoue avec les nombres négatifs. $float=-1.4 donne 0 avec cette méthode. Ce n'est pas ce qu'ils ont enseigné dans mon école. Rappelez-vous que int() est tronqué vers zéro.

78voto

EvdB Points 878

Vous pouvez soit utiliser un module comme Math::Round :

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

Ou vous pouvez le faire de manière brutale :

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

47voto

Kyle Points 557

Si vous décidez d'utiliser printf ou sprintf, notez qu'ils utilisent l'attribut Arrondir la moitié à pair 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

0 votes

Merci de l'avoir signalé. Plus précisément, le nom de la méthode est "Arrondir la moitié au pair".

0 votes

Toutes les réponses qui mentionnent printf, ou sprintf devraient mentionner ceci.

0 votes

C'est une information extrêmement importante. J'ai eu plusieurs fois des bugs dans des logiciels parce que je supposais que 5 serait toujours arrondi vers le haut. J'ai finalement trouvé, pourquoi perl ne faisait jamais ce que je voulais. Merci de l'avoir signalé.

9voto

Kent Fredric Points 35592

Voir perldoc/perlfaq :

Rappelez-vous que int() simplement tronqué vers 0. Pour l'arrondi à un certain nombre de chiffres certain nombre de chiffres, sprintf() ou printf() est généralement le route la plus facile.

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

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

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

Dans les perles 5.000 à 5.003, la trigonométrie a été faite dans les Math::Complex module.

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

En interne, il utilise le Math::Complex et certaines fonctions peuvent sortir de l'axe réel dans le plan complexe, par exemple le sinus inverse de 2.

L'arrondi dans les applications financières peut avoir de graves conséquences. d'arrondi utilisée doit être spécifiée avec précision. Dans ces cas, il est probablement utile de ne pas de ne pas faire confiance au système d'arrondi utilisé par Perl, mais plutôt d'implémenter vous-même la fonction la fonction d'arrondi dont vous avez besoin.

Pour comprendre pourquoi, remarquez que vous aurez toujours un problème avec l'alternance à mi-chemin :

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 qu'en C. IEEE dit que nous devons faire cela. Les nombres en Perl dont les valeurs absolues sont des entiers inférieurs à 2**31 (sur des 32 bits) fonctionneront à peu près comme des entiers mathématiques. Les autres nombres ne sont pas garantis.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X