109 votes

Python arrondir un nombre entier à la centaine supérieure

Il semble que cette question ait déjà été posée des centaines de fois (les jeux de mots sont amusants =) mais je ne trouve que la fonction d'arrondi des flottants. Comment arrondir un nombre entier, par exemple : 130 -> 200 ?

3 votes

Voulez-vous que 100 soit également arrondi à 200 ?

0 votes

Non, la réponse de Thomas fait exactement ce dont j'ai besoin.

1 votes

La réponse de Thomas fait arrondir 100 à 200. C'est pourquoi j'ai demandé.

202voto

Martin Geisler Points 44779

L'arrondi est généralement effectué sur des nombres à virgule flottante, et il y a ici trois fonctions de base que vous devez connaître : round (arrondi au nombre entier le plus proche), math.floor (toujours arrondi à l'inférieur), et math.ceil (toujours arrondis à l'unité supérieure).

Vous posez des questions sur les nombres entiers et l'arrondi à la centaine, mais nous pouvons toujours utiliser math.ceil tant que vos chiffres sont inférieurs à 2 53 . Pour utiliser math.ceil nous divisons d'abord par 100, nous arrondissons et nous multiplions ensuite par 100 :

>>> import math
>>> def roundup(x):
...     return int(math.ceil(x / 100.0)) * 100
... 
>>> roundup(100)
100
>>> roundup(101)
200

Le fait de diviser par 100 d'abord et de multiplier par 100 ensuite "décale" deux décimales vers la droite et la gauche, de sorte que math.ceil fonctionne sur les centaines. Vous pouvez utiliser 10**n au lieu de 100 si vous voulez arrondir aux dizaines ( n = 1 ), des milliers ( n = 3 ), etc.

Une autre façon de procéder consiste à éviter les nombres à virgule flottante (leur précision est limitée) et à utiliser uniquement des nombres entiers. Les nombres entiers ont une précision arbitraire en Python, ce qui vous permet d'arrondir des nombres de n'importe quelle taille. La règle d'arrondi est simple : trouvez le reste après la division par 100, et ajoutez 100 moins ce reste s'il est différent de zéro :

>>> def roundup(x):
...     return x if x % 100 == 0 else x + 100 - x % 100

Cela fonctionne pour des nombres de toutes tailles :

>>> roundup(100)
100
>>> roundup(130)
200
>>> roundup(1234567891234567891)
1234567891234567900L

J'ai fait un mini-benchmark des deux solutions :

$ python -m timeit -s 'import math' -s 'x = 130' 'int(math.ceil(x/100.0)) * 100'
1000000 loops, best of 3: 0.364 usec per loop
$ python -m timeit -s 'x = 130' 'x if x % 100 == 0 else x + 100 - x % 100'
10000000 loops, best of 3: 0.162 usec per loop

La solution en nombres entiers purs est plus rapide d'un facteur deux par rapport à la solution en nombres entiers. math.ceil solution.

Thomas a proposé une solution basée sur les nombres entiers qui est identique à celle que j'ai ci-dessus, sauf qu'elle utilise une astuce en multipliant les valeurs booléennes. Il est intéressant de voir qu'il n'y a pas d'avantage de vitesse à écrire le code de cette façon :

$ python -m timeit -s 'x = 130' 'x + 100*(x%100>0) - x%100'
10000000 loops, best of 3: 0.167 usec per loop

En guise de remarque finale, permettez-moi également de noter que si vous aviez voulu arrondir 101-149 à 100 et 150-199 à 200, par exemple, arrondir à l le plus proche cent, alors le système intégré round peut le faire pour vous :

>>> int(round(130, -2))
100
>>> int(round(170, -2))
200

0 votes

Je ne fais pas un arrondi normal ici, si c'était le cas, j'utiliserais round()

3 votes

@ofko : c'est vrai, vous voulez arrondir. Le site math.ceil est la façon canonique de le faire - diviser et multiplier par 100 est la façon canonique de faire round , ceil y floor travailler sur des centaines.

1 votes

Après les récentes modifications, il est maintenant logique d'accepter cette réponse.

43voto

Mark Dickinson Points 6780

Cette réponse est tardive, mais il existe une solution simple qui combine les meilleurs aspects des réponses existantes : le prochain multiple de 100 à partir de x es x - x % -100 (ou si vous préférez, x + (-x) % 100 ).

>>> x = 130
>>> x -= x % -100  # Round x up to next multiple of 100.
>>> x
200

C'est rapide et simple, et donne des résultats corrects pour tout nombre entier. x (comme la réponse de John Machin) et donne également des résultats raisonnables (en tenant compte des avertissements habituels concernant la représentation en virgule flottante) si x est un flottant (comme la réponse de Martin Geisler).

>>> x = 0.1
>>> x -= x % -100
>>> x
100.0

1 votes

Votre solution est aussi rapide que celle de Martin mais la notation est plus courte. merci. %timeit 'x = 110' 'x -= x % -100' # 100000000 boucles, meilleur de 3 : 9.37 ns par boucle VS %timeit 'x = 110' 'x + 100*(x%100>0) - x%100' #100000000 boucles, meilleur de 3 : 9.38 ns par boucle

2 votes

Remarque : Pour toujours arrondir à l'unité inférieure, il faut x -= x % +100

25voto

larsmans Points 167484

Essayez ça :

int(round(130 + 49, -2))

0 votes

Pourquoi int() ? type(round(999,-2)) is int (python 3.8)

2 votes

Mais cela ne permet pas toujours d'arrondir les chiffres, ce qui est le but de la question.

19voto

Luke Woodward Points 20417

Voici une méthode générale pour arrondir au multiple le plus proche de tout nombre entier positif :

def roundUpToMultiple(number, multiple):
    num = number + (multiple - 1)
    return num - (num % multiple)

Exemple d'utilisation :

\>>> roundUpToMultiple(101, 100)
200
>>> roundUpToMultiple(654, 321)
963

0 votes

Une méthode équivalente et plus courte : lambda number, multiple: multiple * (1 + (number - 1) // multiple)

8voto

John Machin Points 39706

Para a non-négatif, b positif, tous deux entiers :

>>> rup = lambda a, b: (a + b - 1) // b * b
>>> [(x, rup(x, 100)) for x in (199, 200, 201)]
[(199, 200), (200, 200), (201, 300)]

Mise à jour La réponse actuellement acceptée s'effondre avec des nombres entiers tels que float(x) / float(y) ne peut pas être représenté avec précision comme un float . Voir ce code :

import math

def geisler(x, y): return int(math.ceil(x / float(y))) * y

def orozco(x, y): return x + y * (x % y > 0) - x % y

def machin(x, y): return (x + y - 1) // y * y

for m, n in (
    (123456789123456789, 100),
    (1234567891234567891, 100),
    (12345678912345678912, 100),
    ):
    print; print m, "m"; print n, "n"
    for func in (geissler, orozco, machin):
        print func(m, n), func.__name__

Sortie :

123456789123456789 m
100 n
123456789123456800 geisler
123456789123456800 orozco
123456789123456800 machin

1234567891234567891 m
100 n
1234567891234568000 geisler <<<=== wrong
1234567891234567900 orozco
1234567891234567900 machin

12345678912345678912 m
100 n
12345678912345680000 geisler <<<=== wrong
12345678912345679000 orozco
12345678912345679000 machin

Et voici quelques horaires :

>\python27\python -m timeit -s "import math;x =130" "int(math.ceil(x/100.0))*100"
1000000 loops, best of 3: 0.342 usec per loop

>\python27\python -m timeit -s "x = 130" "x + 100 * (x % 100 > 0) - x % 100"
10000000 loops, best of 3: 0.151 usec per loop

>\python27\python -m timeit -s "x = 100" "(x + 99) // 100 * 100"
10000000 loops, best of 3: 0.0903 usec per loop

0 votes

I know the OP was about rounding an integer - mais je voulais souligner que si vous essayez d'utiliser ces 3 options sur (0.5,10), je m'attends à ce qu'elles retournent 10, alors les deux premières méthodes (geisler & orozco) retournent 10 comme prévu, tandis que machin retourne 0.

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