Sljedeće objašnjava kako zaokružiti brojeve u Pythonu zaokružujući ili zaokružujući na paran broj. Pretpostavlja se da su brojevi tipa float s pomičnim zarezom ili integer int.
- ugrađena funkcija (npr. u programskom jeziku):
round()
- Zaokružite decimale na bilo koji broj znamenki.
- Zaokružite cijele brojeve na bilo koji broj znamenki.
- round() zaokružuje na paran broj, a ne na uobičajeno zaokruživanje
- standardna biblioteka
decimal
quantize()
Decimal
Stvaranje objekta- Zaokruživanje decimala na bilo koji broj znamenki i zaokruživanje na parne brojeve
- Zaokruživanje cijelih brojeva na bilo koji broj znamenki i zaokruživanje na parne brojeve
- Definirajte novu funkciju
- Zaokružite decimale na bilo koji broj znamenki.
- Zaokružite cijele brojeve na bilo koji broj znamenki
- Napomena: Za negativne vrijednosti
Imajte na umu da, kao što je gore spomenuto, zaokruživanje ugrađene funkcije nije općenito zaokruživanje, već zaokruživanje na paran broj. Za detalje pogledajte u nastavku.
ugrađena funkcija (npr. u programskom jeziku):round()
Round() se nudi kao ugrađena funkcija. Može se koristiti bez uvoza modula.
Prvi argument je izvorni broj, a drugi argument je broj znamenki (na koliko znamenki zaokružiti).
Zaokružite decimale na bilo koji broj znamenki.
Sljedeći je primjer obrade za tip float s pomičnim zarezom.
Ako je drugi argument izostavljen, zaokružuje se na cijeli broj. Tip također postaje cjelobrojni int tip.
f = 123.456 print(round(f)) # 123 print(type(round(f))) # <class 'int'>
Ako je naveden drugi argument, on vraća tip float s pomičnim zarezom.
Ako je naveden pozitivan cijeli broj, navedeno je decimalno mjesto; ako je naveden negativan cijeli broj, navedeno je cijelobrojno mjesto. -1 zaokružuje na najbližu desetinu, -2 zaokružuje na najbližu stotinu i 0 zaokružuje na cijeli broj (prvo mjesto), ali vraća tip s plutajućim brojem, za razliku od kada je izostavljen.
print(round(f, 1)) # 123.5 print(round(f, 2)) # 123.46 print(round(f, -1)) # 120.0 print(round(f, -2)) # 100.0 print(round(f, 0)) # 123.0 print(type(round(f, 0))) # <class 'float'>
Zaokružite cijele brojeve na bilo koji broj znamenki.
Sljedeći je primjer obrade za integer int tip.
Ako je drugi argument izostavljen ili ako je naveden 0 ili pozitivan cijeli broj, izvorna vrijednost se vraća onakva kakva jest. Ako je naveden negativan cijeli broj, zaokružuje se na odgovarajuću cjelobrojnu znamenku. U oba slučaja vraća se cijeli broj tipa int.
i = 99518 print(round(i)) # 99518 print(round(i, 2)) # 99518 print(round(i, -1)) # 99520 print(round(i, -2)) # 99500 print(round(i, -3)) # 100000
round() zaokružuje na paran broj, a ne na uobičajeno zaokruživanje
Imajte na umu da se zaokruživanje s ugrađenom funkcijom round() u Pythonu 3 zaokružuje na paran broj, a ne na općenito zaokruživanje.
Kao što je napisano u službenoj dokumentaciji, 0,5 se zaokružuje na 0, 5 se zaokružuje na 0, i tako dalje.
print('0.4 =>', round(0.4)) print('0.5 =>', round(0.5)) print('0.6 =>', round(0.6)) # 0.4 => 0 # 0.5 => 0 # 0.6 => 1 print('4 =>', round(4, -1)) print('5 =>', round(5, -1)) print('6 =>', round(6, -1)) # 4 => 0 # 5 => 0 # 6 => 10
Definicija zaokruživanja na paran broj je sljedeća.
Ako je razlomak manji od 0,5, zaokružite ga prema dolje; ako je udio veći od 0,5, zaokružite ga prema gore; ako je razlomak točno 0,5, zaokružite ga na paran broj između zaokruživanja prema dolje i zaokruživanju prema gore.
Rounding – Wikipedia
0,5 nije uvijek skraćeno.
print('0.5 =>', round(0.5)) print('1.5 =>', round(1.5)) print('2.5 =>', round(2.5)) print('3.5 =>', round(3.5)) print('4.5 =>', round(4.5)) # 0.5 => 0 # 1.5 => 2 # 2.5 => 2 # 3.5 => 4 # 4.5 => 4
U nekim slučajevima definicija zaokruživanja na paran broj ne vrijedi ni za obradu nakon dva decimalna mjesta.
print('0.05 =>', round(0.05, 1)) print('0.15 =>', round(0.15, 1)) print('0.25 =>', round(0.25, 1)) print('0.35 =>', round(0.35, 1)) print('0.45 =>', round(0.45, 1)) # 0.05 => 0.1 # 0.15 => 0.1 # 0.25 => 0.2 # 0.35 => 0.3 # 0.45 => 0.5
To je zbog činjenice da se decimale ne mogu točno prikazati kao brojevi s pomičnim zarezom, kao što je navedeno u službenoj dokumentaciji.
Ponašanje round() za brojeve s pomičnim zarezom može vas iznenaditi:Na primjer, krug (2,675, 2) će vam dati 2,67 umjesto 2,68 kako se očekivalo. Ovo nije bug.:To je rezultat činjenice da se većina decimala ne može točno prikazati brojevima s pomičnim zarezom.
round() — Built-in Functions — Python 3.10.2 Documentation
Ako želite postići općenito zaokruživanje ili točno zaokruživanje decimala na parne brojeve, možete koristiti standardnu knjižnicu decimalnog kvantiziranja (opisano u nastavku) ili definirati novu funkciju.
Također imajte na umu da round() u Pythonu 2 nije zaokruživanje na paran broj, već zaokruživanje.
quantize() decimale standardne biblioteke
Decimalni modul standardne biblioteke može se koristiti za rukovanje točnim decimalnim brojevima s pomičnim zarezom.
Koristeći quantize() metodu decimalnog modula, moguće je zaokružiti brojeve specificiranjem načina zaokruživanja.
- decimal quantize() — Decimal fixed point and floating point arithmetic — Python 3.10.2 Documentation
- Rounding modes — Decimal fixed point and floating point arithmetic — Python 3.10.2 Documentation
Postavljene vrijednosti za zaokruživanje argumenata metode quantize() imaju sljedeća značenja.
ROUND_HALF_UP
:Opće zaokruživanjeROUND_HALF_EVEN
:Zaokruživanje na parne brojeve
Decimalni modul je standardna biblioteka, tako da nije potrebna dodatna instalacija, ali je neophodan uvoz.
from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_EVEN
Stvaranje decimalnog objekta
Decimal() se može koristiti za kreiranje objekata tipa Decimal.
Ako navedete tip float kao argument, možete vidjeti kako se vrijednost zapravo tretira.
print(Decimal(0.05)) # 0.05000000000000000277555756156289135105907917022705078125 print(type(Decimal(0.05))) # <class 'decimal.Decimal'>
Kao što je prikazano u primjeru, 0,05 se ne tretira kao točno 0,05. To je razlog zašto je ugrađena funkcija round() opisana gore zaokružila na vrijednost različitu od očekivane za decimalne vrijednosti uključujući 0,05 u primjeru.
Budući da je 0,5 jedna polovica (-1 stepen od 2), može se točno izraziti u binarnom zapisu.
print(Decimal(0.5)) # 0.5
Ako navedete vrstu stringa str umjesto tipa float, on će se tretirati kao decimalni tip točne vrijednosti.
print(Decimal('0.05')) # 0.05
Zaokruživanje decimala na bilo koji broj znamenki i zaokruživanje na parne brojeve
Pozovite quantize() iz objekta tipa Decimal da biste zaokružili vrijednost.
Prvi argument quantize() je niz s istim brojem znamenki kao i broj znamenki koje želite pronaći, kao što je ‘0,1’ ili ‘0,01’.
Dodatno, argument ROUNDING specificira način zaokruživanja; ako je navedeno ROUND_HALF_UP, koristi se opće zaokruživanje.
f = 123.456 print(Decimal(str(f)).quantize(Decimal('0'), rounding=ROUND_HALF_UP)) # 123 print(Decimal(str(f)).quantize(Decimal('0.1'), rounding=ROUND_HALF_UP)) # 123.5 print(Decimal(str(f)).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)) # 123.46
Za razliku od ugrađene funkcije round(), 0,5 se zaokružuje na 1.
print('0.4 =>', Decimal(str(0.4)).quantize(Decimal('0'), rounding=ROUND_HALF_UP)) print('0.5 =>', Decimal(str(0.5)).quantize(Decimal('0'), rounding=ROUND_HALF_UP)) print('0.6 =>', Decimal(str(0.6)).quantize(Decimal('0'), rounding=ROUND_HALF_UP)) # 0.4 => 0 # 0.5 => 1 # 0.6 => 1
Ako je zaokruživanje argumenta postavljeno na ROUND_HALF_EVEN, zaokruživanje se izvodi na parne brojeve kao u ugrađenoj funkciji round().
Kao što je gore spomenuto, ako je tip float s pomičnim zarezom naveden kao argument Decimal(), on se tretira kao Decimal objekt s vrijednošću jednakom stvarnoj vrijednosti tipa float, tako da je rezultat korištenja quantize() metoda će se razlikovati od očekivanog, baš kao i ugrađena funkcija round().
print('0.05 =>', round(0.05, 1)) print('0.15 =>', round(0.15, 1)) print('0.25 =>', round(0.25, 1)) print('0.35 =>', round(0.35, 1)) print('0.45 =>', round(0.45, 1)) # 0.05 => 0.1 # 0.15 => 0.1 # 0.25 => 0.2 # 0.35 => 0.3 # 0.45 => 0.5 print('0.05 =>', Decimal(0.05).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.15 =>', Decimal(0.15).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.25 =>', Decimal(0.25).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.35 =>', Decimal(0.35).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.45 =>', Decimal(0.45).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) # 0.05 => 0.1 # 0.15 => 0.1 # 0.25 => 0.2 # 0.35 => 0.3 # 0.45 => 0.5
Ako je argument Decimal() naveden kao niz tipa str, on se tretira kao Decimalni objekt točno te vrijednosti, tako da je rezultat očekivan.
print('0.05 =>', Decimal(str(0.05)).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.15 =>', Decimal(str(0.15)).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.25 =>', Decimal(str(0.25)).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.35 =>', Decimal(str(0.35)).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.45 =>', Decimal(str(0.45)).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) # 0.05 => 0.0 # 0.15 => 0.2 # 0.25 => 0.2 # 0.35 => 0.4 # 0.45 => 0.4
Budući da se tipom float može ispravno rukovati 0,5, nema problema u određivanju tipa float kao argumenta Decimal() kada se zaokružuje na cijeli broj, ali je sigurnije navesti string tip str kada se zaokružuje na decimalno mjesto.
Na primjer, 2,675 je zapravo 2,67499…. u float tipu. Stoga, ako želite zaokružiti na dvije decimale, morate navesti niz na Decimal(), inače će rezultat biti drugačiji od očekivanog rezultata bez obzira zaokružite li na najbliži cijeli broj (ROUND_HALF_UP) ili na paran broj (ROUND_HALF_EVEN ).
print(Decimal(2.675)) # 2.67499999999999982236431605997495353221893310546875 print(Decimal(2.675).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)) # 2.67 print(Decimal(str(2.675)).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)) # 2.68 print(Decimal(2.675).quantize(Decimal('0.01'), rounding=ROUND_HALF_EVEN)) # 2.67 print(Decimal(str(2.675)).quantize(Decimal('0.01'), rounding=ROUND_HALF_EVEN)) # 2.68
Imajte na umu da metoda quantize() vraća broj tipa Decimal, tako da ako želite raditi s brojem s plutajućim brojem, trebate ga pretvoriti u float tip pomoću float(), inače će doći do pogreške.
d = Decimal('123.456').quantize(Decimal('0.01'), rounding=ROUND_HALF_UP) print(d) # 123.46 print(type(d)) # <class 'decimal.Decimal'> # print(1.2 + d) # TypeError: unsupported operand type(s) for +: 'float' and 'decimal.Decimal' print(1.2 + float(d)) # 124.66
Zaokruživanje cijelih brojeva na bilo koji broj znamenki i zaokruživanje na parne brojeve
Ako želite zaokružiti na cjelobrojnu znamenku, navođenjem nečega poput ’10’ kao prvog argumenta nećete dobiti željeni rezultat.
i = 99518 print(Decimal(i).quantize(Decimal('10'), rounding=ROUND_HALF_UP)) # 99518
To je zato što quantize() izvodi zaokruživanje prema eksponentu Decimal objekta, ali eksponent Decimal(’10’) je 0, a ne 1.
Možete odrediti proizvoljan eksponent korištenjem E kao stringa eksponenta (npr. ‘1E1’). Eksponent eksponenta može se provjeriti metodom as_tuple.
print(Decimal('10').as_tuple()) # DecimalTuple(sign=0, digits=(1, 0), exponent=0) print(Decimal('1E1').as_tuple()) # DecimalTuple(sign=0, digits=(1,), exponent=1)
Takav kakav jest, rezultat će biti u eksponencijalnom zapisu koristeći E. Ako želite koristiti normalnu notaciju, ili ako želite raditi s int int tipom nakon zaokruživanja, upotrijebite int() da pretvorite rezultat.
print(Decimal(i).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP)) # 9.952E+4 print(int(Decimal(i).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP))) # 99520 print(int(Decimal(i).quantize(Decimal('1E2'), rounding=ROUND_HALF_UP))) # 99500 print(int(Decimal(i).quantize(Decimal('1E3'), rounding=ROUND_HALF_UP))) # 100000
Ako je zaokruživanje argumenta postavljeno na ROUND_HALF_UP, doći će do općeg zaokruživanja, npr. 5 će se zaokružiti na 10.
print('4 =>', int(Decimal(4).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP))) print('5 =>', int(Decimal(5).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP))) print('6 =>', int(Decimal(6).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP))) # 4 => 0 # 5 => 10 # 6 => 10
Naravno, nema problema ako ga navedete kao niz.
Definirajte novu funkciju
Metoda korištenja decimalnog modula je točna i sigurna, ali ako vam ne odgovara pretvorba tipa, možete definirati novu funkciju za postizanje općeg zaokruživanja.
Postoji mnogo mogućih načina za to, na primjer, sljedeća funkcija.
def my_round(val, digit=0): p = 10 ** digit return (val * p * 2 + 1) // 2 / p
Ako ne trebate specificirati broj znamenki i uvijek zaokružiti na prvu decimalu, možete koristiti jednostavniji obrazac.
my_round_int = lambda x: int((x * 2 + 1) // 2)
Ako trebate biti precizni, sigurnije je koristiti decimalni.
Sljedeće je samo za referencu.
Zaokružite decimale na bilo koji broj znamenki.
print(int(my_round(f))) # 123 print(my_round_int(f)) # 123 print(my_round(f, 1)) # 123.5 print(my_round(f, 2)) # 123.46
Za razliku od kruga, 0,5 postaje 1 prema općem zaokruživanju.
print(int(my_round(0.4))) print(int(my_round(0.5))) print(int(my_round(0.6))) # 0 # 1 # 1
Zaokružite cijele brojeve na bilo koji broj znamenki
i = 99518 print(int(my_round(i, -1))) # 99520 print(int(my_round(i, -2))) # 99500 print(int(my_round(i, -3))) # 100000
Za razliku od kruga, 5 postaje 10 prema uobičajenom zaokruživanju.
print(int(my_round(4, -1))) print(int(my_round(5, -1))) print(int(my_round(6, -1))) # 0 # 10 # 10
Napomena: Za negativne vrijednosti
U gornjem primjeru funkcije, -0,5 je zaokruženo na 0.
print(int(my_round(-0.4))) print(int(my_round(-0.5))) print(int(my_round(-0.6))) # 0 # 0 # -1
Postoje različiti načini razmišljanja o zaokruživanju za negativne vrijednosti, ali ako želite pretvoriti -0,5 u -1, možete to izmijeniti na sljedeći način, na primjer
import math def my_round2(val, digit=0): p = 10 ** digit s = math.copysign(1, val) return (s * val * p * 2 + 1) // 2 / p * s print(int(my_round2(-0.4))) print(int(my_round2(-0.5))) print(int(my_round2(-0.6))) # 0 # -1 # -1