Semble qu'on aurait déjà dû lui demander des centaines de fois (les jeux de mots sont amusants =) mais je ne trouve que la fonction pour arrondir les flotteurs. Comment arrondir un entier, par exemple: 130 -> 200
?
L'arrondi est généralement effectué sur des nombres à virgule flottante, et ici, vous devez connaître trois fonctions de base: round
(arrondit à l'entier le plus proche), math.floor
(arrondit toujours vers le bas) et math.ceil
(toujours arrondi).
Vous demandez des nombres entiers et des arrondis à des centaines, mais nous pouvons toujours utiliser math.ceil
tant que vos nombres sont inférieurs à 253. Utiliser math.ceil
, nous divisons simplement par 100 en premier, arrondissons et multiplions par 100 par la suite:
>>> import math
>>> def roundup(x):
... return int(math.ceil(x / 100.0)) * 100
...
>>> roundup(100)
100
>>> roundup(101)
200
En divisant par 100 en premier et en multipliant par 100 par la suite, "décale" deux décimales vers la droite et vers la gauche pour que math.ceil
fonctionne sur des centaines. Vous pouvez utiliser 10**n
au lieu de 100 si vous voulez arrondir à des dizaines (n = 1
), milliers (n = 3
), etc.
Une autre manière de procéder consiste à éviter les nombres à virgule flottante (ils ont une précision limitée) et à utiliser à la place des entiers uniquement. Les entiers ont une précision arbitraire en Python, ce qui vous permet d'arrondir des nombres de n'importe quelle taille. La règle pour l'arrondi est simple: trouvez le reste après la division avec 100, et ajoutez 100 moins ce reste s'il n'est pas nul:
>>> def roundup(x):
... return x if x % 100 == 0 else x + 100 - x % 100
Cela fonctionne pour les numéros de toute taille:
>>> 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 entière pure est plus rapide d'un facteur deux par rapport au math.ceil
Solution.
Thomas a proposé une solution basée sur des 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 aucun 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
Pour terminer, permettez-moi de noter également que si vous aviez voulu arrondir 101–149 à 100 et arrondir 150–199 à 200, par exemple, arrondir au le plus proche cent, alors la fonction round
intégrée peut le faire pour vous:
>>> int(round(130, -2))
100
>>> int(round(170, -2))
200
Essaye ça:
int(round(130 + 49, -2))
Il s'agit d'une réponse tardive, mais il existe une solution simple qui combine les meilleurs aspects des réponses existantes: le multiple suivant de 100
À partir de x
est 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, donne des résultats corrects pour tout entier x
(comme la réponse de John Machin) et donne également des résultats raisonnables (modulo les mises en garde habituelles sur la représentation en virgule flottante) si x
est un flotteur (comme la réponse de Martin Geisler).
>>> x = 0.1
>>> x -= x % -100
>>> x
100.0
Voici un moyen général d'arrondir au multiple le plus proche d'un 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
Pour a
non négatif, b
positif, les 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)]
pdate La réponse actuellement acceptée s'effondre avec des 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
Si votre int est x: x + 100 - x % 100
Cependant, comme indiqué dans les commentaires, cela retournera 200 si x==100
.
Si ce n'est pas le comportement attendu, vous pouvez utiliser x + 100*(x%100>0) - x%100
Attention: optimisations prématurées à venir ...
Étant donné que tant de réponses ici font le timing de cela, je voulais ajouter une autre alternative.
Prendre @Martin Geisler
def roundup(x):
return x if x % 100 == 0 else x + 100 - x % 100
(que je préfère pour plusieurs raisons)
mais en tenant compte de l'action%
def roundup2(x):
x100= x % 100
return x if x100 == 0 else x + 100 - x100
Donne une amélioration de la vitesse de ~ 20% par rapport à l'original
def roundup3(x):
x100 = x % 100
return x if not x100 else x + 100 - x100
Est encore meilleur et est ~ 36% plus rapide que l'original
enfin, je pensais que je pouvais supprimer l'opérateur not
et changer l'ordre des branches en espérant que cela augmenterait également la vitesse, mais j'ai été déconcerté de découvrir qu'il est en fait plus lent de retomber pour être seulement 23% plus rapide que l'original.
def roundup4(x):
x100 = x % 100
return x + 100 - x100 if x100 else x
>python -m timeit -s "x = 130" "x if x % 100 == 0 else x + 100 - x % 100"
1000000 loops, best of 3: 0.359 usec per loop
>python -m timeit -s "x = 130" "x100 = x % 100" "x if x100 == 0 else x + 100 - x100"
1000000 loops, best of 3: 0.287 usec per loop
>python -m timeit -s "x = 130" "x100 = x % 100" "x if not x100 else x + 100 - x100"
1000000 loops, best of 3: 0.23 usec per loop
>python -m timeit -s "x = 130" "x100 = x % 100" "x + 100 - x100 if x100 else x"
1000000 loops, best of 3: 0.277 usec per loop
des explications sur les raisons pour lesquelles 3 est plus rapide que 4 seraient les bienvenues.
Essaye ça:
import math
def ceilm(number,multiple):
'''Returns a float rounded up by a factor of the multiple specified'''
return math.ceil(float(number)/multiple)*multiple
Exemple d'utilisation:
>>> ceilm(257,5)
260
>>> ceilm(260,5)
260