Comment arrondissez-vous un nombre en Python?

487

Ce problème me tue. Comment arrondit-on un nombre UP en Python?

J'ai essayé d'arrondir (nombre) mais il arrondit le nombre. Exemple:

round(2.3) = 2.0 and not 3, what I would like

J'ai essayé int (nombre + 0,5) mais il arrondit à nouveau le nombre! Exemple:

int(2.3 + .5) = 2

Ensuite, j'ai essayé le tour (numéro + 0,5) mais cela ne fonctionnera pas dans les cas de bord. Exemple:

WAIT! THIS WORKED!

S'il vous plaît donnez votre avis.

Bodacydo
la source
4
round(number + .5)ne fonctionne pas si le nombre est entier. round(3+.5) == 4, quand vous voulez vraiment 3.
Nearoo

Réponses:

846

La ceil fonction (plafond):

import math
print(math.ceil(4.2))
Steve Tjoa
la source
21
Elaboration: math.ceil retourne le plus petit entier supérieur ou égal à la valeur d'entrée. Cette fonction traite l'entrée comme un flottant (Python n'a pas de variables fortement typées) et la fonction renvoie un flottant. Si vous voulez un int, vous pouvez construire un int à partir de la valeur de retour, c'est-à-direint(math.ceil(363))
RW Sinnet
9
@Sinnet: En fait, on pourrait dire que python est fortement typé stackoverflow.com/a/11328980/5069869
Bernhard
1
@TheEspinosa: Oui, python est définitivement fortement typé, c'est juste que de nombreuses fonctions posent des questions sur le type de certains paramètres et exécutent un code différent en fonction de la réponse.
quamrana
12
@RWSinnet En Python 3, math.ceilretourne un objet entier réel, pas seulement un objet flottant avec une valeur entière.
Arthur Tacca
Faites attention à la précision du flotteur, car le 10000000 * 0.00136 = 13600.000000000002plafond peut augmenter considérablementmath.ceil(10000000 * 0.00136) = 13601.0
ofthestreet
171

Je sais que cette réponse est pour une question de tout à l'heure, mais si vous ne voulez pas importer de mathématiques et que vous voulez simplement arrondir, cela fonctionne pour moi.

>>> int(21 / 5)
4
>>> int(21 / 5) + (21 % 5 > 0)
5

La première partie devient 4 et la deuxième partie est évaluée à "True" s'il y a un reste, qui en plus True = 1; False = 0. Donc, s'il n'y a pas de reste, alors il reste le même entier, mais s'il y a un reste, il ajoute 1.

user3074620
la source
38
Agréable. Vous pouvez également utiliser //pour la division entière, donc cela devient 21 // 5 + (21 % 5 > 0).
naught101
6
C'est la meilleure solution si seuls des entiers sont impliqués. Aucun floatart inutile . Agréable.
Nico Schlömer
158

Problème intéressant de Python 2.x à garder à l'esprit:

>>> import math
>>> math.ceil(4500/1000)
4.0
>>> math.ceil(4500/1000.0)
5.0

Le problème est que la division de deux ints en python produit un autre entier et qui est tronqué avant l'appel du plafond. Vous devez faire une valeur flottante (ou cast) pour obtenir un résultat correct.

En javascript, le même code exact produit un résultat différent:

console.log(Math.ceil(4500/1000));
5
TrophyGeek
la source
44
En Python 2.x : int / int -> int et int / float -> float En Python 3.x : int / int peut entraîner un float
gecco
7
vous pouvez obtenir le comportement de Python 3.x sur certaines versions de Python 2.x en activant la "vraie division" comme indiqué ici
Rob Dennis
110

Si vous travaillez avec des nombres entiers, une façon d'arrondir est de tirer parti du fait que l'arrondi est //bas: Faites simplement la division sur le nombre négatif, puis annulez la réponse. Aucune importation, virgule flottante ou conditionnelle nécessaire.

rounded_up = -(-numerator // denominator)

Par exemple:

>>> print(-(-101 // 5))
21
David Bau
la source
1
Qu'en est-il lorsque vous n'avez pas besoin d'effectuer d'opération mathématique? C'est-à-dire que vous n'avez qu'un seul numéro.
Klik
2
@Klik: alors vous pouvez simplement diviser par 1 ==> - (-num // 1) et vous obtenez votre réponse :-) Bonne journée! David Bau: très belle proposition!
Marco smdm
10
J'ai chronométré toutes les réponses ici et c'était cinq fois plus rapide que le meilleur suivant (math.ceil). @Andreas avait la même heure
mini totent
@minitotent Ce n'est pas surprenant car il s'agit d'une simple division entière et de quelques opérations à cycle unique. C'est le genre de réponse qui vous permet d'obtenir un emploi: comprendre non seulement la langue, mais toutes les couches d'abstractions en dessous.
Nearoo
Agréable! J'ai toujours utilisé (num + den - 1) // den, ce qui est bien pour les intentrées avec des dénominateurs positifs, mais échoue si même un seul non-intégral floatest impliqué (soit le numérateur soit le dénominateur); c'est plus magique, mais ça marche pour ints et floats. Pour les petits numérateurs, c'est aussi plus rapide (sur CPython 3.7.2), bien que curieusement, lorsque seul le numérateur est suffisamment grand pour que des mathématiques basées sur les tableaux soient nécessaires, votre approche est plus lente; on ne sait pas pourquoi, car le travail de division devrait être similaire et deux négations unaires devraient être moins chères que l'addition + la soustraction.
ShadowRanger
56

Vous aimerez aussi numpy:

>>> import numpy as np
>>> np.ceil(2.3)
3.0

Je ne dis pas que c'est mieux que les mathématiques, mais si vous utilisiez déjà numpy à d'autres fins, vous pouvez garder votre code cohérent.

Quoi qu'il en soit, juste un détail que j'ai rencontré. J'utilise beaucoup numpy et j'ai été surpris qu'il ne soit pas mentionné, mais bien sûr, la réponse acceptée fonctionne parfaitement.

Lisa
la source
3
Utiliser numpy est bien aussi. Le plus simple serait avec les mathématiques car il fait déjà partie de python intégré dans les bibliothèques. Cela a plus de sens. Au lieu de cela, comme vous l'avez mentionné, si vous utilisez beaucoup numpy pour d'autres problèmes, il est logique et cohérent d'utiliser numpy.ceil :-) Bon indice!
Marco smdm
30

Utilisezmath.ceil pour arrondir:

>>> import math
>>> math.ceil(5.4)
6.0

REMARQUE : L'entrée doit être flottante.

Si vous avez besoin d'un entier, appelez-le intpour le convertir:

>>> int(math.ceil(5.4))
6

BTW, utilisez math.floorpour arrondir vers le bas et roundarrondir à l'entier le plus proche.

>>> math.floor(4.4), math.floor(4.5), math.floor(5.4), math.floor(5.5)
(4.0, 4.0, 5.0, 5.0)
>>> round(4.4), round(4.5), round(5.4), round(5.5)
(4.0, 5.0, 5.0, 6.0)
>>> math.ceil(4.4), math.ceil(4.5), math.ceil(5.4), math.ceil(5.5)
(5.0, 5.0, 6.0, 6.0)
kennytm
la source
1
L'entrée ne doit pas nécessairement être un flottant si vous utilisez python 3: s'en ceil() occupera en interne
guival
12

La syntaxe n'est peut-être pas aussi pythonique qu'on pourrait le souhaiter, mais c'est une bibliothèque puissante.

https://docs.python.org/2/library/decimal.html

from decimal import *
print(int(Decimal(2.3).quantize(Decimal('1.'), rounding=ROUND_UP)))
NuclearPeon
la source
11

Je suis surpris que personne ne l'ait suggéré

(numerator + denominator - 1) // denominator

pour la division entière avec arrondi. Autrefois la voie commune pour C / C ++ / CUDA (cf. divup)

Andreas Schuh
la source
2
Pertinent uniquement pour les langues typées statiquement. Si le dénominateur est un flotteur, vous êtes mort.
Bharel
Cela ne fonctionne également de manière cohérente que si le dénominateur est positif; si le dénominateur est négatif, vous devez ajouter 1au lieu de le soustraire, ou inverser les signes du numérateur et du dénominateur avant d'effectuer les calculs.
ShadowRanger
7

La valeur arrondie doit être flottante

a = 8 
b = 21
print math.ceil(a / b)
>>> 0

mais

print math.ceil(float(a) / b)
>>> 1.0
Alexey
la source
6

Essaye ça:

a = 211.0
print(int(a) + ((int(a) - a) != 0))
user3712978
la source
1
Intelligent. L' ((int(a) - a) != 0)expression revient 1chaque fois qu'elle adoit être arrondie. Vous voudrez peut-être développer votre réponse et expliquer comment cela fonctionne.
Tom Aranda
@TomAranda Quelqu'un peut-il expliquer comment une expression booléenne se traduit par une valeur s'il vous plaît?
Bowen Liu
6
>>> def roundup(number):
...     return round(number+.5)
>>> roundup(2.3)
3
>>> roundup(19.00000000001)
20

Cette fonction ne nécessite aucun module.

PonasM
la source
Que se passe-t-il si votre numéro est 3, alors il arrondirait à 4ce que quelqu'un peut ou non vouloir
buydadip
15
Cela ne fonctionne que dans 99% des cas. Vous n'y avez pas réfléchi correctement. De telles solutions doivent être évitées à tout prix.
Nearoo
donc au lieu de +.5 faites + .49999999 assez bien pour moi.
FlyingZebra1
5

Les réponses ci-dessus sont correctes, cependant, importer le mathmodule juste pour cette seule fonction me semble généralement un peu exagéré. Heureusement, il existe une autre façon de procéder:

g = 7/5
g = int(g) + (not g.is_integer())

Trueet Falsesont interprétés comme 1et 0dans une déclaration impliquant des nombres en python. g.is_interger()se traduit essentiellement par g.has_no_decimal()ou g == int(g). La dernière déclaration en anglais se lit donc round g down and add one if g has decimal.

Nearoo
la source
1
Et si vous en avez envie, vous pouvez utiliser à la int(g) + (g % 1 > 0)place ;-)
Nearoo
from math import ceilsemble résoudre l'import de l'ensemble du module mathématique :)
SH7890
@ SH7890 J'ai bien peur que cette ligne ne soit pas très différente import mathen termes de ce qui se passe dans les coulisses. Il supprime juste tous les symboles sauf ceil.
Nearoo
5

Sans importer math // en utilisant l'environnement de base:

a) méthode / méthode de classe

def ceil(fl): 
  return int(fl) + (1 if fl-int(fl) else 0)

def ceil(self, fl): 
  return int(fl) + (1 if fl-int(fl) else 0)

b) lambda:

ceil = lambda fl:int(fl)+(1 if fl-int(fl) else 0)
Kuřátko Zvyk
la source
5

Pour ceux qui veulent arrondir a / bet obtenir un entier:

Une autre variante utilisant la division entière est

def int_ceil(a, b):
    return (a - 1) // b + 1

>>> int_ceil(19, 5)
4
>>> int_ceil(20, 5)
4
>>> int_ceil(21, 5)
5
Pavel
la source
3

Si quelqu'un souhaite arrondir à une décimale spécifique:

import math
def round_up(n, decimals=0):
    multiplier = 10 ** decimals
    return math.ceil(n * multiplier) / multiplier
sans fil
la source
1

Je suis surpris de ne pas avoir encore vu cette réponse round(x + 0.4999), alors je vais la poser. Notez que cela fonctionne avec n'importe quelle version de Python. Les modifications apportées au schéma d'arrondi Python ont rendu les choses difficiles. Voir cet article .

Sans importer, j'utilise:

def roundUp(num):
    return round(num + 0.49)

testCases = list(x*0.1 for x in range(0, 50))

print(testCases)
for test in testCases:
    print("{:5.2f}  -> {:5.2f}".format(test, roundUp(test)))

Pourquoi cela fonctionne

À partir des documents

Pour les types intégrés prenant en charge round (), les valeurs sont arrondies au multiple de 10 le plus proche de la puissance moins n; si deux multiples sont également proches, l'arrondi est effectué vers le choix pair

Par conséquent, 2,5 est arrondi à 2 et 3,5 est arrondi à 4. Si ce n'était pas le cas, l'arrondi pourrait être effectué en ajoutant 0,5, mais nous voulons éviter d'arriver à mi-chemin. Donc, si vous ajoutez 0,4999, vous vous rapprocherez, mais avec suffisamment de marge pour être arrondi à ce que vous attendez normalement. Bien sûr, cela échouera si le x + 0.4999est égal à [n].5000, mais cela est peu probable.

Klik
la source
2
En utilisant 0.4999, il ne donnera pas de résultat correct pour toute entrée comprise entre ???. 0000 et ???. 0001 (intervalle ouvert), pas seulement exactement ???. 0001. Par exemple, si vous l'essayez avec 3.00005, vous obtiendrez un résultat de 3 au lieu du 4. attendu. Bien sûr, vous pouvez réduire la probabilité que cela se produise en ajoutant de plus en plus de chiffres jusqu'à la précision maximale des flottants, mais quel est le indiquer que s'il existe des solutions plus robustes et intuitives, comme utiliser math.ceil()?
blubberdiblub
@blubberdiblub Dans ma réponse, je déclare Without importing I use:. J'ai également mentionné qu'il échouera si le x + 0.4999est égal à [n].5000.
Klik
4
Oui, vous déclarez dans votre réponse que votre solution est sans importation, mais je n'en vois pas la valeur. lemath module et se math.ceil()trouve dans la bibliothèque standard, donc disponible partout à toutes fins pratiques sans installer de trucs supplémentaires. Et en ce qui concerne votre mention de l'échec, cela est incomplet dans votre réponse, car il échoue pour un intervalle entier, pas seulement pour un seul point. Techniquement, vous pourriez affirmer que vous avez raison, comme vous le dites si et non siff , mais cela donnera l'impression au lecteur occasionnel qu'il est moins probable qu'il ne l'est vraiment.
blubberdiblub
0

Pour le faire sans aucune importation:

>>> round_up = lambda num: int(num + 1) if int(num) != num else int(num)
>>> round_up(2.0)
2
>>> round_up(2.1)
3
gorttar
la source
0

Je sais que cela remonte à un certain temps, mais j'ai trouvé une réponse assez intéressante, alors voici:

-round(-x-0.5)

Cela corrige les cas de bords et fonctionne pour les nombres positifs et négatifs, et ne nécessite aucune importation de fonction

À votre santé

Fenmaz
la source
2
Ce sera encore -round(-x-0.3) = x
arrondi
0

lorsque vous utilisez 4500/1000 en python, le résultat sera 4, car pour le python par défaut, asume comme entier le résultat, logiquement: 4500/1000 = 4.5 -> int (4.5) = 4 et le plafond de 4 est évidemment 4

en utilisant 4500 / 1000,0, le résultat sera 4,5 et un plafond de 4,5 -> 5

En utilisant javascript, vous recevrez 4.5 comme résultat de 4500/1000, car javascript n'assume que le résultat en "type numérique" et renvoie un résultat directement en float

Bonne chance!!

erick vicente
la source
Cela n'est vrai que dans Python 2.x. En Python 3, la division avec un seul /entraîne toujours un flottant, donc 4500/1000toujours 4,5.
Nearoo
0

Si vous ne voulez rien importer, vous pouvez toujours écrire votre propre fonction simple comme:

def RoundUP(num): if num== int(num): return num return int(num + 1)

Sebin
la source
2
Cela ne fonctionne pas si num est 2,05. Vous devez avoir au moins autant de chiffres avec un 9 que votre entrée, vous laissant avec un 0,999 ... ce qui est 1. Mais alors votre cas de coin 2 est à nouveau arrondi. - Eh bien, je suppose qu'il y a une raison pour laquelle math.ceil est là.
Johannes Maria Frank
-1

Vous pouvez utiliser la déviation du sol et y ajouter 1. 2,3 // 2 + 1

user6612280
la source
2
ou utiliser ceil()au lieu de faire bizarrement le contraire et ensuite compenser
guival
2
Ça ne marchera pas. Par exemple:from math import ceil; assert 4 // 2 + 1 == ceil(4 / 2)
Carl Thomé
-1

Je pense que vous confondez les mécanismes de travail entre int()etround() .

int()tronque toujours les nombres décimaux si un nombre flottant est donné; tandis que round(), dans le cas 2.52et 3sont tous deux à égale distance de 2.5, Python retourne celui qui est le plus éloigné du point 0.

round(2.5) = 3
int(2.5) = 2
SooBin Kim
la source
"arrondir" signifie que, par exemple, 2.3est transformé en 3, ce qui ne se produit dans aucun de vos exemples.
Nearoo
-2

Mon partage

J'ai testé l' print(-(-101 // 5)) = 21exemple donné ci-dessus.

Maintenant pour arrondir:

101 * 19% = 19.19

Je ne peux pas utiliser **donc je répartis le multiplier en division:

(-(-101 //(1/0.19))) = 20
andres
la source
-3

Je suis fondamentalement un débutant chez Python, mais si vous essayez simplement d'arrondir au lieu de descendre, pourquoi ne pas le faire:

round(integer) + 1
Daniel
la source
2
Cela ne fonctionnera pas pour tout entier i où 2,5 <entier <3. La valeur souhaitée après arrondi est 3 mais votre expression la transformera en 4.
Pranav Shukla
1
Je pense que vous voulez round(integer + 0.5)dire que c'est ce que je fais souvent
Klik