У наставку је објашњено како заокружити бројеве у Питхон-у заокружујући или заокружујући на паран број. Претпоставља се да су бројеви типа флоат са помичним зарезом или интегер инт.
- уграђена функција (нпр. у програмском језику):
round()
- Заокружите децимале на било који број цифара.
- Заокружите целе бројеве на било који број цифара.
- роунд() заокружује на паран број, а не на уобичајено заокруживање
- стандардна библиотека
decimal
quantize()
Decimal
Креирање објекта- Заокруживање децимала на било који број цифара и заокруживање на парне бројеве
- Заокруживање целих бројева на било који број цифара и заокруживање на парне бројеве
- Дефинишите нову функцију
- Заокружите децимале на било који број цифара.
- Заокружите целе бројеве на било који број цифара
- Напомена: За негативне вредности
Имајте на уму да, као што је горе поменуто, заокруживање уграђене функције није опште заокруживање, већ заокруживање на паран број. Погледајте испод за детаље.
уграђена функција (нпр. у програмском језику):round()
Роунд() је обезбеђен као уграђена функција. Може се користити без увоза модула.
Први аргумент је оригинални број, а други аргумент је број цифара (на колико цифара треба заокружити).
Заокружите децимале на било који број цифара.
Следи пример обраде за тип са плутајућим зарезом.
Ако је други аргумент изостављен, заокружује се на цео број. Тип такође постаје целобројни инт тип.
f = 123.456 print(round(f)) # 123 print(type(round(f))) # <class 'int'>
Ако је наведен други аргумент, он враћа тип са помичним зарезом.
Ако је наведен позитиван цео број, наводи се децимално место; ако је наведен негативан цео број, наведено је целобројно место. -1 се заокружује на најближу десетину, -2 заокружује на најближу стоту и 0 заокружује на цео број (прво место), али враћа тип са плутајућим бројем, за разлику од када се изостави.
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'>
Заокружите целе бројеве на било који број цифара.
Следи пример обраде целобројног типа инт.
Ако је други аргумент изостављен, или ако је наведен 0 или позитиван цео број, оригинална вредност се враћа онаква каква јесте. Ако је наведен негативан цео број, он се заокружује на одговарајућу цифру целог броја. У оба случаја, враћа се целобројни инт тип.
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
роунд() заокружује на паран број, а не на уобичајено заокруживање
Имајте на уму да се заокруживање са уграђеном функцијом роунд() у Питхон 3 заокружује на паран број, а не на опште заокруживање.
Као што је написано у званичној документацији, 0,5 се заокружује на 0, 5 се заокружује на 0, и тако даље.
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
Дефиниција заокруживања на паран број је следећа.
Ако је разломак мањи од 0,5, заокружите га надоле; ако је разломак већи од 0,5, заокружити га; ако је разломак тачно 0,5, заокружите га на паран број између заокруживања наниже и заокруживања нагоре.
Rounding – Wikipedia
0,5 није увек скраћено.
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
У неким случајевима, дефиниција заокруживања на паран број не важи ни за обраду после две децимале.
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
То је због чињенице да се децимале не могу тачно представити као бројеви са покретним зарезом, као што је наведено у званичној документацији.
Понашање роунд() за бројеве са покретним зарезом може да вас изненади:На пример, круг (2,675, 2) ће вам дати 2,67 уместо 2,68 као што се очекивало. Ово није грешка.:Ово је резултат чињенице да већина децимала не може бити тачно представљена бројевима са покретним зарезом.
round() — Built-in Functions — Python 3.10.2 Documentation
Ако желите да постигнете опште заокруживање или тачно заокруживање децимала на парне бројеве, можете користити стандардну библиотеку децималног квантовања (описано у наставку) или дефинисати нову функцију.
Такође имајте на уму да роунд() у Питхон-у 2 није заокруживање на паран број, већ заокруживање.
куантизе() децимале стандардне библиотеке
Децимални модул стандардне библиотеке може се користити за руковање тачним децималним бројевима са покретним зарезом.
Користећи методу куантизе() децималног модула, могуће је заокружити бројеве навођењем начина заокруживања.
- 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
Постављене вредности за заокруживање аргумената методе куантизе() имају следећа значења, респективно.
ROUND_HALF_UP
:Опште заокруживањеROUND_HALF_EVEN
:Заокруживање на парне бројеве
Децимални модул је стандардна библиотека, тако да није потребна додатна инсталација, али је неопходан увоз.
from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_EVEN
Креирање децималног објекта
Децимал() се може користити за креирање објеката типа Децимал.
Ако наведете тип флоат као аргумент, можете видети како се вредност заправо третира.
print(Decimal(0.05)) # 0.05000000000000000277555756156289135105907917022705078125 print(type(Decimal(0.05))) # <class 'decimal.Decimal'>
Као што је приказано у примеру, 0,05 се не третира као тачно 0,05. Ово је разлог зашто је уграђена функција роунд() описана изнад заокружила на другачију вредност од очекиване за децималне вредности укључујући 0,05 у примеру.
Пошто је 0,5 једна половина (-1 степен од 2), може се тачно изразити у бинарној нотацији.
print(Decimal(0.5)) # 0.5
Ако наведете тип стринга стр уместо типа флоат, он ће се третирати као децимални тип тачне вредности.
print(Decimal('0.05')) # 0.05
Заокруживање децимала на било који број цифара и заокруживање на парне бројеве
Позовите куантизе() из објекта типа Децимал да бисте заокружили вредност.
Први аргумент куантизе() је стринг са истим бројем цифара као и број цифара које желите да пронађете, као што је ‘0.1’ или ‘0.01’.
Поред тога, аргумент РОУНДИНГ специфицира начин заокруживања; ако је назначено РОУНД_ХАЛФ_УП, користи се опште заокруживање.
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
За разлику од уграђене функције роунд(), 0,5 се заокружује на 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
Ако је заокруживање аргумента постављено на РОУНД_ХАЛФ_ЕВЕН, заокруживање се врши на парне бројеве као у уграђеној функцији роунд().
Као што је горе поменуто, ако је тип флоат са помичним зарезом наведен као аргумент Децимал(), он се третира као Децимал објекат са вредношћу једнаком стварној вредности типа флоат, тако да је резултат коришћења куантизе() метод ће се разликовати од онога што се очекује, баш као и уграђена функција роунд().
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
Ако је аргумент Децимал() наведен као стринг типа стр, он се третира као Децимални објекат тачно те вредности, тако да је резултат очекиван.
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
Пошто тип флоат може исправно да обради 0,5, нема проблема у навођењу типа флоат као аргумента Децимал() када се заокружује на цео број, али је сигурније навести стринг тип стр када се заокружује на децимално место.
На пример, 2,675 је у ствари 2,67499…. у плутајућем облику. Стога, ако желите да заокружите на две децимале, морате да наведете стринг на Децимал(), иначе ће резултат бити другачији од очекиваног резултата било да заокружујете на најближи цео број (РОУНД_ХАЛФ_УП) или на паран број (РОУНД_ХАЛФ_ЕВЕН ).
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
Имајте на уму да метода куантизе() враћа број типа децималног типа, тако да ако желите да оперишете са бројем типа флоат, потребно је да га конвертујете у флоат тип помоћу флоат(), иначе ће доћи до грешке.
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
Заокруживање целих бројева на било који број цифара и заокруживање на парне бројеве
Ако желите да заокружите на цео број, навођење нечег попут ’10’ као првог аргумента неће вам дати жељени резултат.
i = 99518 print(Decimal(i).quantize(Decimal('10'), rounding=ROUND_HALF_UP)) # 99518
То је зато што куантизе() обавља заокруживање према експоненту Децимал објекта, али експонент Децимал(’10’) је 0, а не 1.
Можете да наведете произвољан експонент користећи Е као стринг експонента (нпр. ‘1Е1’). Експонент експонента се може проверити у методи ас_тупле.
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)
Како јесте, резултат ће бити у експоненцијалној нотацији користећи Е. Ако желите да користите нормалну нотацију, или ако желите да радите са целим бројем типа инт након заокруживања, користите инт() да конвертујете резултат.
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
Ако је заокруживање аргумента постављено на РОУНД_ХАЛФ_УП, доћи ће до општег заокруживања, нпр. 5 ће бити заокружено на 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
Наравно, нема проблема ако га наведете као стринг.
Дефинишите нову функцију
Метод коришћења децималног модула је прецизан и сигуран, али ако вам није пријатна конверзија типа, можете дефинисати нову функцију да бисте постигли опште заокруживање.
Постоји много могућих начина да се то уради, на пример, следећа функција.
def my_round(val, digit=0): p = 10 ** digit return (val * p * 2 + 1) // 2 / p
Ако не морате да наведете број цифара и увек заокружите на прву децималу, можете користити једноставнији образац.
my_round_int = lambda x: int((x * 2 + 1) // 2)
Ако треба да будете прецизни, сигурније је користити децимални.
Следеће је само за референцу.
Заокружите децимале на било који број цифара.
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
За разлику од рунде, 0,5 постаје 1 према општем заокруживању.
print(int(my_round(0.4))) print(int(my_round(0.5))) print(int(my_round(0.6))) # 0 # 1 # 1
Заокружите целе бројеве на било који број цифара
i = 99518 print(int(my_round(i, -1))) # 99520 print(int(my_round(i, -2))) # 99500 print(int(my_round(i, -3))) # 100000
За разлику од круга, 5 постаје 10 према уобичајеном заокруживању.
print(int(my_round(4, -1))) print(int(my_round(5, -1))) print(int(my_round(6, -1))) # 0 # 10 # 10
Напомена: За негативне вредности
У примеру функције изнад, -0,5 је заокружено на 0.
print(int(my_round(-0.4))) print(int(my_round(-0.5))) print(int(my_round(-0.6))) # 0 # 0 # -1
Постоје различити начини размишљања о заокруживању негативних вредности, али ако желите да претворите -0,5 у -1, можете то изменити на следећи начин, нпр.
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