Jak zaokrąglasz liczbę w Pythonie?

486

Ten problem mnie zabija. W jaki sposób jedno zaokrąglenie liczby UP w Pythonie?

Próbowałem zaokrąglić (liczbę), ale zaokrągliłem liczbę w dół. Przykład:

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

Próbowałem int (liczba + .5), ale ponownie zaokrągla liczbę w dół! Przykład:

int(2.3 + .5) = 2

Potem próbowałem zaokrąglić (liczba + .5), ale to nie zadziała w przypadku krawędzi. Przykład:

WAIT! THIS WORKED!

Proszę doradź.

bodacydo
źródło
4
round(number + .5)nie działa, jeśli liczba jest liczbą całkowitą. round(3+.5) == 4, kiedy naprawdę chcesz 3.
Nearoo

Odpowiedzi:

844

Ceil (pułap) Funkcja:

import math
print(math.ceil(4.2))
Steve Tjoa
źródło
21
Opracowanie: math.ceil zwraca najmniejszą liczbę całkowitą, która jest większa lub równa wartości wejściowej. Ta funkcja traktuje dane wejściowe jako zmiennoprzecinkowe (Python nie ma silnie typowanych zmiennych), a funkcja zwraca zmiennoprzecinkowe. Jeśli chcesz int, możesz zbudować int z wartości zwracanej, tj.int(math.ceil(363))
RW Sinnet
9
@Sinnet: Właściwie można powiedzieć, że python jest silnie napisany stackoverflow.com/a/11328980/5069869
Bernhard
1
@TheEspinosa: Tak, python jest zdecydowanie silnie typowany, tyle że wiele funkcji zadaje pytania dotyczące rodzaju niektórych parametrów i wykonuje różne kody w zależności od odpowiedzi.
quamrana
12
@RWSinnet W Pythonie 3 math.ceilzwraca rzeczywisty obiekt całkowity, a nie tylko obiekt pływający o wartości całkowitej.
Arthur Tacca
Zadbaj o precyzję pływaka, ponieważ 10000000 * 0.00136 = 13600.000000000002sufit może znacznie zwiększyćmath.ceil(10000000 * 0.00136) = 13601.0
OFTESTREET 10.0919
170

Wiem, że ta odpowiedź jest na pytanie od jakiegoś czasu, ale jeśli nie chcesz importować matematyki i chcesz po prostu zaokrąglić w górę, to działa dla mnie.

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

Pierwsza część staje się 4, a druga część przyjmuje wartość „Prawda”, jeśli pozostała część, która dodatkowo Prawda = 1; False = 0. Więc jeśli nie ma reszty, to pozostaje ta sama liczba całkowita, ale jeśli jest reszta, dodaje 1.

użytkownik3074620
źródło
38
Miły. Możesz także użyć //do dzielenia liczb całkowitych, więc staje się 21 // 5 + (21 % 5 > 0).
naught101
6
To najlepsze rozwiązanie, jeśli w grę wchodzą tylko liczby całkowite. Bez zbędnych floats. Miły.
Nico Schlömer,
158

Interesujący problem z Python 2.x, o którym należy pamiętać:

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

Problem polega na tym, że podzielenie dwóch liczb całkowitych w pythonie powoduje powstanie kolejnej liczby wewnętrznej, która jest obcięta przed wywołaniem pułapu. Musisz ustawić jedną wartość jako zmiennoprzecinkową (lub rzutową), aby uzyskać poprawny wynik.

W javascript ten sam kod daje inny wynik:

console.log(Math.ceil(4500/1000));
5
TrophyGeek
źródło
44
W Pythonie 2.x : int / int -> int i int / float -> float W Pythonie 3.x : int / int może wystąpić float
gecco
7
możesz uzyskać Python 3.x o zachowaniu w niektórych wersjach Python 2.x poprzez włączenie „prawdziwego podziału”, jak pokazano tutaj
Rob Dennis
110

Jeśli pracujesz z liczbami całkowitymi, jednym ze sposobów zaokrąglania w górę jest skorzystanie z faktu, że //zaokrągla w dół: po prostu wykonaj podział na liczbę ujemną, a następnie zaneguj odpowiedź. Nie jest wymagany import, zmiennoprzecinkowy ani warunkowy.

rounded_up = -(-numerator // denominator)

Na przykład:

>>> print(-(-101 // 5))
21
David Bau
źródło
1
Co powiesz na to, że nie musisz wykonywać żadnych operacji matematycznych? Tj. Masz tylko jeden numer.
Klik
2
@Klik: możesz po prostu podzielić przez 1 ==> - (-num // 1), a otrzymasz odpowiedź :-) Miłego dnia! David Bau: bardzo fajna propozycja!
Marco smdm
10
Zmierzyłem czas na wszystkie odpowiedzi tutaj i było to pięć razy szybciej niż następny najlepszy (math.ceil). @Andreas miał ten sam czas
mini totent
@minitotent Nie jest to zaskakujące, ponieważ jest to prosty podział na liczby całkowite i kilka operacji w jednym cyklu. Oto odpowiedź na pytanie: Zrozumienie nie tylko języka, ale wszystkich warstw abstrakcji pod nim.
Nearoo
Miły! Zawsze używałem (num + den - 1) // den, co jest dobre w przypadku intdanych wejściowych z dodatnimi mianownikami, ale kończy się niepowodzeniem, jeśli floatzaangażowana jest nawet pojedyncza niecałkowita (licznik lub mianownik); jest to bardziej magicznie wyglądające, ale działa zarówno na ints, jak i na floats. W przypadku małych liczników jest on również szybszy (w CPython 3.7.2), choć dziwnie, gdy tylko licznik jest wystarczająco duży, aby potrzebować matematyki opartej na tablicy, twoje podejście jest wolniejsze; nie jest jasne, dlaczego tak jest, ponieważ podział pracy powinien być podobny, a dwa jednoznaczne negacje powinny być tańsze niż dodawanie + odejmowanie.
ShadowRanger
56

Możesz także polubić numpy:

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

Nie twierdzę, że to lepsze niż matematyka, ale jeśli już używałeś numpy do innych celów, możesz zachować spójność kodu.

W każdym razie tylko szczegół, z którym się spotkałem. Często używam numpy i byłem zaskoczony, że nie wspomniano o nim, ale oczywiście zaakceptowana odpowiedź działa doskonale.

Lisa
źródło
3
Używanie numpy też jest fajne. Najłatwiej byłoby z matematyką, ponieważ jest ona już częścią wbudowanych bibliotek Pythona. To ma więcej sensu. Zamiast tego, jak wspomniałeś, jeśli używasz dużo numpy do innych problemów, wtedy sensowne i spójne jest używanie numpy.ceil :-) Dobra wskazówka!
Marco smdm
30

Użyj,math.ceil aby zaokrąglić w górę:

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

UWAGA : Wejście powinno być zmiennoprzecinkowe.

Jeśli potrzebujesz liczby całkowitej, zadzwoń, intaby ją przekonwertować:

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

BTW, użyj, math.flooraby zaokrąglić w dół i roundzaokrąglić do najbliższej liczby całkowitej.

>>> 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
źródło
1
Dane wejściowe niekoniecznie muszą być zmiennoprzecinkowe, jeśli używasz Pythona 3: ceil() zajmie się tym wewnętrznie
guival
11

Dziwię się, że nikt nie zasugerował

(numerator + denominator - 1) // denominator

do dzielenia liczb całkowitych z zaokrąglaniem w górę. Kiedyś był powszechnym sposobem dla C / C ++ / CUDA (por. divup)

Andreas Schuh
źródło
2
Dotyczy tylko języków o typie statycznym. Jeśli mianownikiem jest liczba zmiennoprzecinkowa, nie żyjesz.
Bharel,
Działa to również konsekwentnie tylko wtedy, gdy mianownik jest dodatni; jeśli mianownik jest ujemny, 1przed wykonaniem matematyki należy go dodać zamiast odjąć lub odwrócić znaki zarówno licznika, jak i mianownika.
ShadowRanger
7

Zaokrąglona wartość powinna być zmienna

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

ale

print math.ceil(float(a) / b)
>>> 1.0
Alexey
źródło
6

Spróbuj tego:

a = 211.0
print(int(a) + ((int(a) - a) != 0))
użytkownik3712978
źródło
1
Sprytny. Te ((int(a) - a) != 0)powroty ekspresji 1, gdy amusi być zaokrąglone. Możesz poszerzyć swoją odpowiedź i wyjaśnić, jak to działa.
Tom Aranda,
@TomAranda Czy ktoś może wyjaśnić, w jaki sposób wyrażenie logiczne ocenia na wartość?
Bowen Liu,
6
>>> def roundup(number):
...     return round(number+.5)
>>> roundup(2.3)
3
>>> roundup(19.00000000001)
20

Ta funkcja nie wymaga modułów.

PonasM
źródło
Co jeśli twój numer to 3, to zaokrągliby w górę do tego, 4co może lub nie być tym, czego ktoś chce
buydadip
15
Działa to tylko w 99% wszystkich przypadków. Nie przemyślałeś tego właściwie. Takich rozwiązań należy unikać za wszelką cenę.
Nearoo
więc zamiast +.5 do + .49999999 wystarczy dla mnie.
FlyingZebra1
5

Powyższe odpowiedzi są poprawne, jednak importowanie mathmodułu tylko dla tej jednej funkcji zwykle wydaje mi się przesadą. Na szczęście istnieje inny sposób:

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

Truei Falsesą interpretowane jako 1oraz 0w instrukcji zawierającej liczby w pythonie. g.is_interger()w zasadzie tłumaczy się na g.has_no_decimal()lub g == int(g). Tak więc ostatnie zdanie w języku angielskim brzmiround g down and add one if g has decimal .

Nearoo
źródło
1
A jeśli masz ochotę, możesz użyć int(g) + (g % 1 > 0) zamiast tego ;-)
Nearoo
from math import ceilwydaje się naprawić importowanie całego modułu matematycznego :)
SH7890
@ SH7890 Obawiam się, że ta linia nie różni się zbytnio import mathod tego, co dzieje się za kulisami. Po prostu upuszcza wszystkie symbole oprócz ceil.
Nearoo
5

Bez importowania matematyki // przy użyciu podstawowego środowiska:

a) metoda / metoda klasy

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
źródło
5

Dla tych, którzy chcą zaokrąglić w górę a / b i uzyskać liczbę całkowitą:

Innym wariantem wykorzystującym dzielenie liczb całkowitych jest

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
źródło
3

Jeśli ktoś chce zaokrąglić w górę do określonego miejsca po przecinku:

import math
def round_up(n, decimals=0):
    multiplier = 10 ** decimals
    return math.ceil(n * multiplier) / multiplier
osuwireless
źródło
1

Dziwię się, że jeszcze nie widziałem tej odpowiedzi round(x + 0.4999), więc odłożę ją. Zauważ, że działa to z każdą wersją Pythona. Zmiany wprowadzone w schemacie zaokrąglania w Pythonie utrudniają pracę. Zobacz ten post .

Bez importowania używam:

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)))

Dlaczego to działa

Z dokumentów

W przypadku wbudowanych typów obsługujących round () wartości są zaokrąglane do najbliższej wielokrotności 10 do potęgi minus n; jeśli dwa wielokrotności są jednakowo blisko siebie, zaokrąglanie odbywa się w kierunku równego wyboru

Dlatego 2,5 zostaje zaokrąglone do 2, a 3,5 zaokrąglone do 4. Jeśli tak nie było, zaokrąglanie w górę można wykonać, dodając 0,5, ale chcemy uniknąć dotarcia do połowy. Tak więc, jeśli dodasz 0,4999, zbliżysz się, ale z wystarczającym marginesem, aby zostać zaokrąglonym do tego, czego normalnie byś oczekiwał. Oczywiście to się nie powiedzie, jeśli x + 0.4999jest równe [n].5000, ale jest to mało prawdopodobne.

Klik
źródło
2
Przy użyciu 0,4999 nie da poprawnego wyniku dla żadnego wejścia pomiędzy ???. 0000 a ???. 0001 (przerwa otwarta), nie tylko dokładnie ???. 0001. Na przykład, jeśli wypróbujesz to z 3.00005, otrzymasz wynik 3 zamiast oczekiwanego 4. Oczywiście możesz zmniejszyć prawdopodobieństwo tego, dodając coraz więcej cyfr do maksymalnej precyzji liczb zmiennoprzecinkowych, ale jaka jest wskaż, że jeśli masz pod ręką bardziej solidne i intuicyjne rozwiązania, takie jak używanie math.ceil()?
blubberdiblub
@blubberdiblub W mojej odpowiedzi stwierdzam Without importing I use:. Wspomniałem również, że to się nie powiedzie, jeśli x + 0.4999jest równe [n].5000.
Klik
4
Tak, w odpowiedzi podajesz, że twoje rozwiązanie nie wymaga importu, ale nie widzę jego wartości. mathModuł i math.ceil()jest w bibliotece standardowej, więc wszędzie dostępne dla wszystkich praktycznych celów bez instalowania dodatkowych rzeczy. A jeśli chodzi o twoją wzmiankę o tym, kiedy zawodzi, nie jest to kompletna odpowiedź, ponieważ zawodzi przez cały okres, a nie tylko przez jeden punkt. Technicznie rzecz biorąc, można argumentować, masz rację, jak mówisz , jeśli nie wtedy i tylko wtedy , ale to zrobi wrażenie na przypadkowego czytelnika, że jest mniej prawdopodobne, niż jest w rzeczywistości.
blubberdiblub
0

Aby to zrobić bez importu:

>>> 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
źródło
0

Wiem, że to już dawno temu, ale znalazłem dość interesującą odpowiedź, więc oto:

-round(-x-0.5)

Naprawia to przypadki krawędzi i działa zarówno dla liczb dodatnich, jak i ujemnych i nie wymaga importu żadnej funkcji

Twoje zdrowie

Fenmaz
źródło
2
To będzie nadal zaokrąglać w dół-round(-x-0.3) = x
Diblo Dk
0

kiedy operujesz 4500/1000 w Pythonie, wynik będzie wynosił 4, ponieważ dla domyślnego Pythona przyjmujemy jako liczbę całkowitą wynik, logicznie: 4500/1000 = 4.5 -> int (4.5) = 4 i pułap 4 oczywiście wynosi 4

przy użyciu 4500 / 1000.0 wynik wyniesie 4,5, a pułap 4,5 -> 5

Za pomocą javascript otrzymasz 4.5 jako wynik 4500/1000, ponieważ javascript przyjmuje tylko wynik jako „typ liczbowy” i zwraca wynik bezpośrednio jako zmiennoprzecinkowy

Powodzenia!!

erick vicente
źródło
Dotyczy to tylko Python 2.x. W Pythonie 3 dzielenie pojedynczym /zawsze powoduje liczbę zmiennoprzecinkową, więc 4500/1000zawsze wynosi 4.5.
Nearoo
0

Jeśli nie chcesz niczego importować, zawsze możesz napisać własną prostą funkcję jako:

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

Sebin
źródło
2
To nie działa, jeśli num to 2.05. Musisz mieć co najmniej tyle cyfr z cyfrą 9 co dane wejściowe, pozostawiając ci 0.999 ... co oznacza 1. Ale wtedy twoja przypadek narożny 2 jest ponownie zaokrąglany w górę. - Cóż, wydaje mi się, że istnieje powód, dla którego istnieje matematyka. Cewka.
Johannes Maria Frank
-1

Możesz użyć podziału podłogi i dodać do niego 1. 2,3 // 2 + 1

user6612280
źródło
2
lub użyj ceil()zamiast dziwnie robić coś przeciwnego, a następnie zrekompensować
porada
2
To nie zadziała. Na przykład:from math import ceil; assert 4 // 2 + 1 == ceil(4 / 2)
Carl Thomé
-1

Myślę, że mylisz mechanizmy robocze między int()i round().

int()zawsze obcina liczby dziesiętne, jeśli podano liczbę zmiennoprzecinkową; podczas gdy round()w przypadku 2.5gdzie 2i 3oba są w równej odległości 2.5, Python zwraca cokolwiek, co jest bardziej oddalone od punktu 0.

round(2.5) = 3
int(2.5) = 2
SooBin Kim
źródło
„zaokrąglanie w górę” oznacza, że ​​np. 2.3zmienia się w 3, co nie dzieje się w żadnym z twoich przykładów.
Nearoo
-2

Moja część

Testowałem print(-(-101 // 5)) = 21 podany przykład powyżej.

Teraz do zaokrąglania w górę:

101 * 19% = 19.19

Nie mogę użyć, **więc podzielę mnożnik na dział:

(-(-101 //(1/0.19))) = 20
Andres
źródło
-3

Jestem w zasadzie początkującym w Python, ale jeśli próbujesz zaokrąglić w górę zamiast w dół, dlaczego nie:

round(integer) + 1
Daniel
źródło
2
To nie zadziała dla żadnej liczby całkowitej i, gdzie 2,5 <liczba całkowita <3. Pożądana wartość po zaokrągleniu w górę wynosi 3, ale twoje wyrażenie zamieni ją w 4.
Pranav Shukla
1
Myślę, że masz na myśli round(integer + 0.5)To, co często robię
Klik