Python хэл дээрх аравтын бутархай болон бүхэл тоог “дугуй” болон “Аравтын тоогоор дугуйлах. quantize

Бизнес эрхэлдэг

Дараах нь Python хэл дээр тоонуудыг тэгш тоо хүртэл дугуйлах эсвэл дугуйлах замаар хэрхэн дугуйлахыг тайлбарладаг. Тоонууд нь хөвөгч цэгийн хөвөгч эсвэл бүхэл тоон int төрлийн байна гэж үздэг.

  • суулгасан функц (жишээ нь програмчлалын хэл дээр):round()
    • Аравтын бутархайг дурын тооны цифр хүртэл дугуйруулна.
    • Бүхэл тоог дурын тооны оронтой тоонд дугуйлна.
    • round() нь энгийн бөөрөнхийлөлт рүү биш, тэгш тоо руу дугуйлна
  • стандарт номын санdecimalquantize()
    • DecimalОбъект үүсгэх
    • Аравтын бутархайг дурын тооны цифр хүртэл, тэгш тоо хүртэл дугуйруулна
    • Бүхэл тоог дурын тооны оронтой тоо хүртэл бөөрөнхийлж, тэгш тоо хүртэл дугуйлах
  • Шинэ функцийг тодорхойлох
    • Аравтын бутархайг дурын тооны цифр хүртэл дугуйруулна.
    • Бүхэл тоог дурын тооны оронтой тоонд дугуйлна
    • Тайлбар: Сөрөг утгын хувьд

Дээр дурдсанчлан, суурилуулсан функц нь ерөнхий дугуйрсан биш, харин тэгш тоо хүртэл дугуйрсан гэдгийг анхаарна уу. Дэлгэрэнгүйг доороос үзнэ үү.

суулгасан функц (жишээ нь програмчлалын хэл дээр):round()

Round() нь суурилуулсан функцээр хангагдсан. Үүнийг ямар ч модуль импортлохгүйгээр ашиглах боломжтой.

Эхний аргумент нь анхны дугаар, хоёр дахь аргумент нь цифрүүдийн тоо (хэдэн орон руу дугуйлах вэ) юм.

Аравтын бутархайг дурын тооны цифр хүртэл дугуйруулна.

Дараах нь хөвөгч цэгийн хөвөгч төрлийг боловсруулах жишээ юм.

Хэрэв хоёр дахь аргументыг орхигдуулсан бол бүхэл тоо болгон дугуйруулна. Төрөл нь мөн бүхэл тоон int төрөл болно.

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

Бүхэл тоог дурын тооны оронтой тоонд дугуйлна.

Дараах нь бүхэл тоон int төрлийн боловсруулалтын жишээ юм.

Хэрэв хоёр дахь аргументыг орхигдуулсан эсвэл 0 эсвэл эерэг бүхэл тоо зааж өгсөн бол анхны утгыг байгаагаар нь буцаана. Хэрэв сөрөг бүхэл тоо заасан бол түүнийг харгалзах бүхэл тоонд дугуйруулна. Аль ч тохиолдолд бүхэл тоо 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() нь энгийн бөөрөнхийлөлт рүү биш, тэгш тоо руу дугуйлна

Python 3-т суурилуулсан round() функцээр дугуйлах нь ерөнхий бөөрөнхийлөлт биш харин тэгш тоо хүртэл дугуйлахыг анхаарна уу.

Албан ёсны баримт бичигт бичсэнээр 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

Энэ нь албан ёсны баримт бичигт заасны дагуу аравтын бутархайг яг хөвөгч цэгийн тоогоор илэрхийлэх боломжгүйтэй холбоотой юм.

Хөвөгч цэгт зориулсан round() функц таныг гайхшруулж магадгүй юм:Жишээлбэл, round(2.675, 2) нь таамаглаж байсанчлан 2.68 биш харин 2.67-г өгнө. Энэ алдаа биш.:Энэ нь ихэнх аравтын бутархайг хөвөгч цэгээр яг таг илэрхийлэх боломжгүй байдгийн үр дүн юм.
round() — Built-in Functions — Python 3.10.2 Documentation

Хэрэв та аравтын бутархайг тэгш тоо болгон ерөнхий бөөрөнхийлөх эсвэл нарийн бөөрөнхийлөхийг хүсвэл стандарт номын сангийн аравтын бутархай хэмжигдэхүүнийг (доор тайлбарласан) ашиглах эсвэл шинэ функцийг тодорхойлж болно.

Мөн Python 2 дээрх round() нь тэгш тоо руу бөөрөнхийлдөггүй, харин дугуйрдаг гэдгийг анхаарна уу.

стандарт номын сангийн аравтын бутархайн quantize().

Стандарт номын сангийн аравтын модулийг яг аравтын бутархайн хөвөгч цэгийн тоог боловсруулахад ашиглаж болно.

Аравтын бутархайн модулийн quantize() аргыг ашиглан дугуйлах горимыг зааж өгснөөр тоог дугуйлах боломжтой.

Quantize() аргын аргументыг дугуйлах багц утгууд нь дараах утгатай байна.

  • ROUND_HALF_UP:Ерөнхий дугуйлах
  • ROUND_HALF_EVEN:Тэгш тоо хүртэл дугуйлах

Аравтын модуль нь стандарт номын сан тул нэмэлт суулгах шаардлагагүй, харин импортлох шаардлагатай.

from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_EVEN

Аравтын тооллын объект үүсгэх

Decimal()-ыг Decimal төрлийн объект үүсгэхэд ашиглаж болно.

Хэрэв та хөвөх төрлийг аргумент болгон зааж өгвөл тухайн утгыг яг юу гэж үзэж байгааг харж болно.

print(Decimal(0.05))
# 0.05000000000000000277555756156289135105907917022705078125

print(type(Decimal(0.05)))
# <class 'decimal.Decimal'>

Жишээлбэл, 0.05-ыг яг 0.05 гэж тооцдоггүй. Дээр тайлбарласан round() функц нь жишээн дээрх 0.05-ыг багтаасан аравтын бутархайн утгуудын хувьд хүлээгдэж байснаас өөр утга болгон дугуйлсан шалтгаан нь энэ юм.

0.5 нь хагас (2-ын -1 хүч) тул үүнийг хоёртын тэмдэглэгээгээр яг таг илэрхийлж болно.

print(Decimal(0.5))
# 0.5

Хэрэв та хөвөгч хэлбэрийн оронд str мөрийн төрлийг зааж өгвөл яг утгын Аравтын төрөл гэж тооцогдоно.

print(Decimal('0.05'))
# 0.05

Аравтын бутархайг дурын тооны цифр хүртэл, тэгш тоо хүртэл дугуйруулна

Аравтын төрлийн объектоос quantize()-г дуудаж утгыг бөөрөнхийлөнө.

quantize()-ын эхний аргумент нь ‘0.1’ эсвэл ‘0.01’ гэх мэт олохыг хүссэн цифрүүдийн тоотой ижил тооны цифр бүхий мөр юм.

Үүнээс гадна, ROUNDING аргумент нь дугуйлах горимыг зааж өгдөг; Хэрэв ROUND_ALF_UP гэж заасан бол ерөнхий дугуйралтыг ашиглана.

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

Суулгасан round() функцээс ялгаатай нь 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

Хэрэв аргументыг бөөрөнхийлөлтийг ROUND_HALF_EVEN гэж тохируулсан бол round() функцийн нэгэн адил тэгш тоогоор дугуйруулна.

Дээр дурдсанчлан хөвөгч цэгийн хөвөгч төрлийг Decimal()-ын аргумент болгон зааж өгсөн бол түүнийг хөвөгч цэгийн төрлийн бодит утгатай тэнцүү утгатай Аравтын объект гэж тооцдог тул quantize()-г ашигласны үр дүн гарна. Уг арга нь 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

Хэрэв Decimal() аргументыг str төрлийн мөр болгон зааж өгсөн бол түүнийг яг тэр утгын Аравтын объект гэж үзэх тул үр дүн нь хүлээгдэж буй шиг байна.

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-ыг хөвөх төрлөөр зөв зохицуулах боломжтой тул бүхэл тоо руу бөөрөнхийлөхдөө Decimal()-ын аргумент болгон хөвөх төрлийг зааж өгөхөд асуудал гарахгүй, харин аравтын бутархай руу дугуйлах үед str мөрийн төрлийг зааж өгөх нь илүү найдвартай.

Жишээ нь, 2.675 нь үнэндээ 2.67499…. float төрлийн. Тиймээс, хэрэв та аравтын хоёр орон хүртэл дугуйлахыг хүсвэл Аравтын тоо () руу тэмдэгт мөрийг зааж өгөх ёстой, эс тэгвээс хамгийн ойрын бүхэл тоо (ROUND_HALF_UP) эсвэл тэгш тоо (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

quantize() арга нь Аравтын төрлийн тоог буцаадаг тул хэрэв та хөвөгч төрлийн тоо дээр ажиллахыг хүсвэл float() ашиглан үүнийг хөвөгч төрөл рүү хөрвүүлэх хэрэгтэй, эс тэгвээс алдаа гарна.

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

Учир нь quantize() нь Decimal объектын илтгэгчийн дагуу бөөрөнхийлдөг боловч Decimal(’10’)-ын илтгэгч нь 1 биш харин 0 байна.

Та E-г илтгэгчийн тэмдэгт мөр болгон ашиглан дурын илтгэгчийг зааж өгч болно (жишээ нь, ‘1E1’). Экспонент илтгэгчийг 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)

Үр дүн нь E-г ашиглан экспоненциал тэмдэглэгээнд байх болно. Хэрэв та ердийн тэмдэглэгээг ашиглахыг хүсвэл эсвэл бөөрөнхийлсний дараа бүхэл тоон int төрлийг ашиглахыг хүсвэл үр дүнг хөрвүүлэхийн тулд 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

Хэрэв аргументыг бөөрөнхийлөлтийг ROUND_ALF_UP гэж тохируулсан бол ерөнхий бөөрөнхийлөлт хийгдэх бөгөөд жишээлбэл, 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