ข้อมูลต่อไปนี้จะอธิบายวิธีการปัดเศษตัวเลขใน Python โดยการปัดเศษหรือปัดเศษเป็นเลขคู่ ตัวเลขจะถือว่าเป็นทศนิยมทศนิยมหรือประเภท int จำนวนเต็ม
- ฟังก์ชันในตัว (เช่น ในภาษาโปรแกรม):
round()
- ปัดเศษทศนิยมเป็นจำนวนหลักเท่าใดก็ได้
- ปัดเศษจำนวนเต็มเป็นจำนวนหลักเท่าใดก็ได้
- round() ปัดเศษเป็นเลขคู่ ไม่ใช่การปัดเศษทั่วไป
- ห้องสมุดมาตรฐาน
decimal
quantize()
Decimal
การสร้างวัตถุ- การปัดเศษทศนิยมเป็นจำนวนหลักใด ๆ และการปัดเศษเป็นเลขคู่
- การปัดเศษจำนวนเต็มเป็นจำนวนหลักใดๆ และการปัดเศษเป็นเลขคู่
- กำหนดฟังก์ชันใหม่
- ปัดเศษทศนิยมเป็นจำนวนหลักเท่าใดก็ได้
- ปัดเศษจำนวนเต็มเป็นจำนวนหลัก
- หมายเหตุ: สำหรับค่าลบ
โปรดทราบว่าดังที่กล่าวไว้ข้างต้น ฟังก์ชัน Round ในตัวไม่ใช่การปัดเศษทั่วไป แต่เป็นการปัดเศษเป็นจำนวนคู่ ดูรายละเอียดด้านล่าง
ฟังก์ชันในตัว (เช่น ในภาษาโปรแกรม):round()
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'>
ปัดเศษจำนวนเต็มเป็นจำนวนหลักเท่าใดก็ได้
ต่อไปนี้คือตัวอย่างการประมวลผลสำหรับชนิด integer 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() ปัดเศษเป็นเลขคู่ ไม่ใช่การปัดเศษทั่วไป
โปรดทราบว่าการปัดเศษด้วยฟังก์ชัน round() ในตัวใน Python 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
นี่เป็นเพราะความจริงที่ว่าทศนิยมไม่สามารถแสดงเป็นตัวเลขทศนิยมได้ตรงตามที่ระบุไว้ในเอกสารอย่างเป็นทางการ
พฤติกรรมของ round() สำหรับตัวเลขทศนิยมอาจทำให้คุณประหลาดใจ:ตัวอย่างเช่น round(2.675, 2) จะให้ 2.67 แทนที่จะเป็น 2.68 ตามที่คาดไว้ นี่ไม่ใช่ข้อผิดพลาด:นี่เป็นผลมาจากข้อเท็จจริงที่ว่าทศนิยมส่วนใหญ่ไม่สามารถแสดงด้วยตัวเลขทศนิยมได้อย่างแม่นยำ
round() — Built-in Functions — Python 3.10.2 Documentation
ถ้าคุณต้องการให้การปัดเศษทั่วไปหรือการปัดเศษทศนิยมเป็นจำนวนคู่อย่างแม่นยำ คุณสามารถใช้ควอนไทซ์ทศนิยมของไลบรารีมาตรฐาน (อธิบายไว้ด้านล่าง) หรือกำหนดฟังก์ชันใหม่
โปรดทราบด้วยว่า round() ใน Python 2 ไม่ได้ปัดเศษเป็นเลขคู่ แต่เป็นการปัดเศษ
quantize() ของทศนิยมไลบรารีมาตรฐาน
โมดูลทศนิยมของไลบรารีมาตรฐานสามารถใช้เพื่อจัดการกับตัวเลขทศนิยมที่แน่นอนได้
การใช้เมธอด quantize() ของโมดูลทศนิยม เป็นไปได้ที่จะปัดเศษตัวเลขโดยระบุโหมดการปัดเศษ
- 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
ค่าที่ตั้งไว้สำหรับการปัดเศษอาร์กิวเมนต์ของเมธอด 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 คือครึ่งหนึ่ง (-1 ยกกำลัง 2) จึงสามารถแสดงเป็นเลขฐานสองได้อย่างแม่นยำ
print(Decimal(0.5)) # 0.5
หากคุณระบุประเภทสตริง str แทนที่จะเป็นประเภททศนิยม จะถือว่าเป็นประเภททศนิยมของค่าที่แน่นอน
print(Decimal('0.05')) # 0.05
การปัดเศษทศนิยมเป็นจำนวนหลักใด ๆ และการปัดเศษเป็นเลขคู่
เรียก quantize() จากวัตถุประเภททศนิยมเพื่อปัดเศษค่า
อาร์กิวเมนต์แรกของ quantize() คือสตริงที่มีจำนวนหลักเท่ากับจำนวนหลักที่คุณต้องการค้นหา เช่น ‘0.1’ หรือ ‘0.01’
นอกจากนี้ อาร์กิวเมนต์ ROUNDING ยังระบุโหมดการปัดเศษ หากระบุ ROUND_HALF_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() จะถือว่าเป็นอ็อบเจ็กต์ทศนิยมที่มีค่าเท่ากับมูลค่าจริงของประเภท float ดังนั้นผลลัพธ์ของการใช้ 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 สามารถจัดการได้อย่างถูกต้องโดยประเภท float จึงไม่มีปัญหาในการระบุประเภท float เป็นอาร์กิวเมนต์ของ Decimal() เมื่อปัดเศษเป็นจำนวนเต็ม แต่จะปลอดภัยกว่าที่จะระบุประเภทสตริง str เมื่อปัดเศษเป็นทศนิยม
ตัวอย่างเช่น 2.675 จริง ๆ แล้ว 2.67499…. ในประเภททุ่น ดังนั้น หากคุณต้องการปัดเศษทศนิยมสองตำแหน่ง คุณต้องระบุสตริงเป็น Decimal() มิฉะนั้น ผลลัพธ์จะแตกต่างจากผลลัพธ์ที่คาดไว้ ไม่ว่าคุณจะปัดเศษเป็นจำนวนเต็มที่ใกล้เคียงที่สุด (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(’10’) คือ 0 ไม่ใช่ 1
คุณสามารถระบุเลขชี้กำลังตามอำเภอใจได้โดยใช้ 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 หากคุณต้องการใช้สัญกรณ์ปกติ หรือหากคุณต้องการทำงานกับชนิด integer 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_HALF_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