Nasledujúci postup vysvetľuje, ako zaokrúhľovať čísla v jazyku Python zaokrúhľovaním alebo zaokrúhľovaním na párne číslo. Predpokladá sa, že čísla sú typu float s pohyblivou rádovou čiarkou alebo int s plávajúcou rádovou čiarkou.
- vstavaná funkcia (napr. v programovacom jazyku):
round()
- Zaokrúhľujte desatinné čísla na ľubovoľný počet číslic.
- Zaokrúhľujte celé čísla na ľubovoľný počet číslic.
- round() zaokrúhľuje na párne číslo, nie na bežné zaokrúhlenie
- štandardná knižnica
decimal
quantize()
Decimal
Vytvorenie objektu- Zaokrúhľovanie desatinných čísel na ľubovoľný počet číslic a zaokrúhľovanie na párne čísla
- Zaokrúhľovanie celých čísel na ľubovoľný počet číslic a zaokrúhľovanie na párne čísla
- Definovanie novej funkcie
- Zaokrúhľujte desatinné čísla na ľubovoľný počet číslic.
- Zaokrúhľovanie celých čísel na ľubovoľný počet číslic
- Poznámka: Pre záporné hodnoty
Všimnite si, že ako bolo uvedené vyššie, vstavaná funkcia round nie je všeobecným zaokrúhľovaním, ale zaokrúhľovaním na párne číslo. Podrobnosti nájdete nižšie.
vstavaná funkcia (napr. v programovacom jazyku): round()
Funkcia Round() je k dispozícii ako vstavaná funkcia. Možno ju používať bez importovania akýchkoľvek modulov.
Prvý argument je pôvodné číslo a druhý argument je počet číslic (na koľko číslic sa zaokrúhľuje).
Zaokrúhľujte desatinné čísla na ľubovoľný počet číslic.
Nasleduje príklad spracovania pre typ float s pohyblivou desatinnou čiarkou.
Ak je druhý argument vynechaný, zaokrúhli sa na celé číslo. Typ sa tiež stane celočíselným typom int.
f = 123.456 print(round(f)) # 123 print(type(round(f))) # <class 'int'>
Ak je zadaný druhý argument, vráti typ float s pohyblivou desatinnou čiarkou.
Ak je zadané kladné celé číslo, je zadané desatinné miesto; ak je zadané záporné celé číslo, je zadané celé miesto. -1 zaokrúhľuje na najbližšiu desatinu, -2 zaokrúhľuje na najbližšiu stotinu a 0 zaokrúhľuje na celé číslo (prvé miesto), ale na rozdiel od vynechania vracia typ float.
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'>
Zaokrúhľujte celé čísla na ľubovoľný počet číslic.
Nasleduje príklad spracovania pre celočíselný typ int.
Ak je druhý argument vynechaný alebo ak je zadaná hodnota 0 alebo celé kladné číslo, vráti sa pôvodná hodnota. Ak je zadané záporné celé číslo, zaokrúhli sa na príslušnú celočíselnú hodnotu. V oboch prípadoch sa vráti celé číslo typu 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() zaokrúhľuje na párne číslo, nie na bežné zaokrúhlenie
Všimnite si, že zaokrúhľovanie pomocou vstavanej funkcie round() v jazyku Python 3 sa zaokrúhľuje na párne číslo, nie na všeobecné zaokrúhlenie.
Ako sa píše v oficiálnej dokumentácii, 0,5 sa zaokrúhľuje na 0, 5 sa zaokrúhľuje na 0 atď.
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
Definícia zaokrúhľovania na párne číslo je nasledovná.
Ak je zlomok menší ako 0,5, zaokrúhlite ho nadol; ak je zlomok väčší ako 0,5, zaokrúhlite ho nahor; ak je zlomok presne 0,5, zaokrúhlite ho nahor na párne číslo medzi zaokrúhlením nadol a nahor.
Rounding – Wikipedia
0,5 nie je vždy skrátený.
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
V niektorých prípadoch sa definícia zaokrúhľovania na párne číslo nevzťahuje ani na spracovanie po dvoch desatinných miestach.
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
Je to spôsobené tým, že desatinné čísla nemožno presne reprezentovať ako čísla s pohyblivou desatinnou čiarkou, ako sa uvádza v oficiálnej dokumentácii.
Správanie funkcie round() pre čísla s pohyblivou rádovou čiarkou vás môže prekvapiť:Napríklad zaokrúhlenie(2,675, 2) vám dá 2,67 namiesto očakávaných 2,68. Toto nie je chyba.:Je to dôsledok toho, že väčšinu desatinných čísel nemožno presne reprezentovať číslami s pohyblivou desatinnou čiarkou.
round() — Built-in Functions — Python 3.10.2 Documentation
Ak chcete dosiahnuť všeobecné zaokrúhľovanie alebo presné zaokrúhľovanie desatinných čísel na párne čísla, môžete použiť kvantifikáciu desatinných čísel štandardnej knižnice (opísanú nižšie) alebo definovať novú funkciu.
Všimnite si tiež, že round() v Pythone 2 nie je zaokrúhľovanie na párne číslo, ale zaokrúhľovanie.
quantize() štandardnej knižnice decimal
Na spracovanie presných desatinných čísel s pohyblivou desatinnou čiarkou možno použiť modul decimal štandardnej knižnice.
Pomocou metódy quantize() modulu decimal je možné zaokrúhľovať čísla zadaním režimu zaokrúhľovania.
- 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
Nastavené hodnoty pre zaokrúhľovanie argumentu metódy quantize() majú nasledujúci význam.
ROUND_HALF_UP
:Všeobecné zaokrúhľovanieROUND_HALF_EVEN
:Zaokrúhľovanie na párne čísla
Modul decimal je štandardná knižnica, takže nie je potrebná žiadna dodatočná inštalácia, ale je potrebné ho importovať.
from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_EVEN
Vytvorenie objektu Decimal
Funkciu Decimal() možno použiť na vytvorenie objektov typu Decimal.
Ak ako argument zadáte typ float, môžete vidieť, ako sa s hodnotou skutočne zaobchádza.
print(Decimal(0.05)) # 0.05000000000000000277555756156289135105907917022705078125 print(type(Decimal(0.05))) # <class 'decimal.Decimal'>
Ako je uvedené v príklade, hodnota 0,05 sa nepovažuje za presnú hodnotu 0,05. To je dôvod, prečo zabudovaná funkcia round() opísaná vyššie zaokrúhľuje na inú hodnotu, ako sa očakáva pre desatinné hodnoty vrátane 0,05 v príklade.
Keďže 0,5 je polovica (-1 mocnina 2), možno ju presne vyjadriť v binárnom zápise.
print(Decimal(0.5)) # 0.5
Ak namiesto typu float zadáte typ string str, bude sa považovať za presnú hodnotu typu Decimal.
print(Decimal('0.05')) # 0.05
Zaokrúhľovanie desatinných čísel na ľubovoľný počet číslic a zaokrúhľovanie na párne čísla
Volanie funkcie quantize() z objektu typu Decimal na zaokrúhlenie hodnoty.
Prvým argumentom funkcie quantize() je reťazec s rovnakým počtom číslic, ako je počet číslic, ktoré chcete nájsť, napríklad '0,1' alebo '0,01'.
Okrem toho argument ROUNDING určuje spôsob zaokrúhľovania; ak je zadaný ROUND_HALF_UP, použije sa všeobecné zaokrúhľovanie.
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
Na rozdiel od vstavanej funkcie round() sa hodnota 0,5 zaokrúhľ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
Ak je argument zaokrúhľovanie nastavený na ROUND_HALF_EVEN, zaokrúhľovanie sa vykonáva na párne čísla ako vo vstavanej funkcii round().
Ako bolo uvedené vyššie, ak je ako argument metódy Decimal() zadaný typ float s pohyblivou desatinnou čiarkou, zaobchádza sa s ním ako s objektom Decimal s hodnotou rovnajúcou sa skutočnej hodnote typu float, takže výsledok použitia metódy quantize() sa bude líšiť od očakávaného, rovnako ako v prípade vstavanej funkcie 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
Ak je argument funkcie Decimal() zadaný ako reťazec typu str, považuje sa za objekt Decimal s presne takouto hodnotou, takže výsledok je podľa očakávania.
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
Keďže 0,5 sa dá správne spracovať pomocou typu float, nie je problém pri zaokrúhľovaní na celé číslo zadať ako argument funkcie Decimal() typ float, ale pri zaokrúhľovaní na desatinné miesto je bezpečnejšie zadať typ string str.
Napríklad 2,675 je v skutočnosti 2,67499…. v type float. Preto ak chcete zaokrúhľovať na dve desatinné miesta, musíte funkcii Decimal() zadať reťazec, inak sa výsledok bude líšiť od očakávaného výsledku, či už zaokrúhľujete na najbližšie celé číslo (ROUND_HALF_UP) alebo na párne číslo (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
Všimnite si, že metóda quantize() vracia číslo typu Decimal, takže ak chcete pracovať s číslom typu float, musíte ho previesť na typ float pomocou metódy float(), inak dôjde k chybe.
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
Zaokrúhľovanie celých čísel na ľubovoľný počet číslic a zaokrúhľovanie na párne čísla
Ak chcete zaokrúhliť na celé číslo, zadaním niečoho ako '10' ako prvého argumentu nezískate požadovaný výsledok.
i = 99518 print(Decimal(i).quantize(Decimal('10'), rounding=ROUND_HALF_UP)) # 99518
Je to preto, lebo funkcia quantize() zaokrúhľuje podľa exponentu objektu Decimal, ale exponent objektu Decimal('10') je 0, nie 1.
Môžete zadať ľubovoľný exponent pomocou reťazca E ako exponent (napr. '1E1'). Exponent exponentu možno skontrolovať v metóde 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)
V tejto podobe bude výsledok v exponenciálnom zápise pomocou E. Ak chcete použiť normálny zápis alebo ak chcete po zaokrúhlení pracovať s celočíselným typom int, použite na prevod výsledku funkciu int().
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
Ak je argument zaokrúhľovanie nastavený na ROUND_HALF_UP, dôjde k všeobecnému zaokrúhľovaniu, napr. 5 sa zaokrúhli 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
Samozrejme, nie je problém, ak ho zadáte ako reťazec.
Definovanie novej funkcie
Metóda použitia desatinného modulu je presná a bezpečná, ale ak vám nevyhovuje typová konverzia, môžete definovať novú funkciu na dosiahnutie všeobecného zaokrúhľovania.
Existuje mnoho možných spôsobov, ako to urobiť, napríklad nasledujúca funkcia.
def my_round(val, digit=0): p = 10 ** digit return (val * p * 2 + 1) // 2 / p
Ak nepotrebujete uvádzať počet číslic a zaokrúhľujete vždy na prvé desatinné miesto, môžete použiť jednoduchší tvar.
my_round_int = lambda x: int((x * 2 + 1) // 2)
Ak potrebujete byť presní, je bezpečnejšie použiť desatinné číslo.
Nasledujúce informácie slúžia len ako referencia.
Zaokrúhľujte desatinné čísla na ľubovoľný počet číslic.
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
Na rozdiel od zaokrúhľovania sa z 0,5 stane 1 podľa všeobecného zaokrúhľovania.
print(int(my_round(0.4))) print(int(my_round(0.5))) print(int(my_round(0.6))) # 0 # 1 # 1
Zaokrúhľovanie celých čísel na ľubovoľný počet číslic
i = 99518 print(int(my_round(i, -1))) # 99520 print(int(my_round(i, -2))) # 99500 print(int(my_round(i, -3))) # 100000
Na rozdiel od zaokrúhľovania sa z 5 stane 10 podľa bežného zaokrúhľovania.
print(int(my_round(4, -1))) print(int(my_round(5, -1))) print(int(my_round(6, -1))) # 0 # 10 # 10
Poznámka: Pre záporné hodnoty
Vo vyššie uvedenom príklade funkcie je -0,5 zaokrúhlené na 0.
print(int(my_round(-0.4))) print(int(my_round(-0.5))) print(int(my_round(-0.6))) # 0 # 0 # -1
O zaokrúhľovaní záporných hodnôt sa dá uvažovať rôznymi spôsobmi, ale ak chcete z hodnoty -0,5 urobiť hodnotu -1, môžete ju upraviť napríklad takto
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