คุณจะปัดเศษตัวเลขใน Python อย่างไร


487

ปัญหานี้กำลังฆ่าฉัน หนึ่งรอบหมายเลขขึ้นในงูหลามได้อย่างไร

ฉันลองปัดเศษ (ตัวเลข) แต่ปัดเศษตัวเลขลง ตัวอย่าง:

round(2.3) = 2.0 and not 3, what I would like

ฉันลอง int (หมายเลข + .5) แต่มันปัดเศษตัวเลขลงอีกรอบ! ตัวอย่าง:

int(2.3 + .5) = 2

จากนั้นฉันลองรอบ (หมายเลข + .5) แต่มันจะไม่ทำงานในกรณีขอบ ตัวอย่าง:

WAIT! THIS WORKED!

กรุณาแนะนำ


4
round(number + .5)ไม่ทำงานหากจำนวนนั้นเป็นจำนวนเต็ม round(3+.5) == 4เมื่อคุณต้องการจริง3
Nearoo

คำตอบ:


845

ceil (เพดาน) ฟังก์ชั่น:

import math
print(math.ceil(4.2))

21
Elaboration: math.ceil ส่งคืนเลขจำนวนเต็มที่เล็กที่สุดซึ่งมากกว่าหรือเท่ากับค่าอินพุต ฟังก์ชั่นนี้ถือว่าอินพุตเป็นแบบลอย (Python ไม่มีตัวแปรที่พิมพ์อย่างรุนแรง) และฟังก์ชั่นจะส่งกลับแบบลอย หากคุณต้องการ int คุณสามารถสร้าง int จากค่าตอบแทนเช่นint(math.ceil(363))
RW Sinnet

9
@Sinnet: จริง ๆ แล้วอาจกล่าวได้ว่าไพ ธ อนพิมพ์อย่างรุนแรงstackoverflow.com/a/11328980/5069869
Bernhard

1
@TheEspinosa: ใช่แล้วไพ ธ อนได้รับการพิมพ์อย่างแน่นอนมันมีฟังก์ชั่นมากมายที่ถามคำถามเกี่ยวกับประเภทของพารามิเตอร์และรันโค้ดที่แตกต่างกันขึ้นอยู่กับคำตอบ
quamrana

12
@RWSinnet ใน Python 3 math.ceilคืนค่าออบเจ็กต์จำนวนเต็มจริงไม่ใช่แค่วัตถุลอยที่มีค่าจำนวนเต็ม
Arthur Tacca

ดูแลความแม่นยำของการลอยเนื่องจาก10000000 * 0.00136 = 13600.000000000002เพดานสามารถเพิ่มขึ้นได้มากmath.ceil(10000000 * 0.00136) = 13601.0
ofthestreet

171

ฉันรู้ว่าคำตอบนี้เป็นคำถามที่ถามกันมานานแล้ว แต่ถ้าคุณไม่ต้องการนำเข้าคณิตศาสตร์และคุณแค่ต้องการปัดเศษมันก็ใช้ได้ผลสำหรับฉัน

>>> int(21 / 5)
4
>>> int(21 / 5) + (21 % 5 > 0)
5

ส่วนแรกจะกลายเป็น 4 และส่วนที่สองประเมินเป็น "จริง" หากมีส่วนที่เหลือซึ่งนอกเหนือจาก True = 1; เท็จ = 0 ดังนั้นถ้าไม่มีเศษเหลือมันก็จะเป็นจำนวนเต็มเหมือนกัน แต่ถ้ามีเศษเหลือก็จะเพิ่ม 1


38
ดี นอกจากนี้คุณยังสามารถใช้สำหรับการแบ่งจำนวนเต็มดังนั้นนี้จะกลายเป็น// 21 // 5 + (21 % 5 > 0)
naught101

6
นี่เป็นทางออกที่ดีที่สุดหากมีจำนวนเต็มเท่านั้นที่เกี่ยวข้อง ไม่มีไม่จำเป็นfloats ดี
Nico Schlömer

158

ปัญหา Python 2.x ที่น่าสนใจที่ควรทราบ:

>>> import math
>>> math.ceil(4500/1000)
4.0
>>> math.ceil(4500/1000.0)
5.0

ปัญหาคือการแบ่งสอง ints ในไพ ธ อนสร้าง int อื่นและที่ถูกตัดทอนก่อนการเรียกเพดาน คุณต้องทำให้ค่าหนึ่งลอย (หรือโยน) เพื่อให้ได้ผลลัพธ์ที่ถูกต้อง

ในจาวาสคริปต์รหัสเดียวกันจะให้ผลลัพธ์ที่แตกต่าง:

console.log(Math.ceil(4500/1000));
5

44
ในPython 2.x : int / int -> int และ int / float -> float ในPython 3.x : int / int อาจส่งผลให้เกิดการลอยได้
gecco

7
คุณสามารถใช้ Python 3.x กับพฤติกรรมใน Python 2.x บางรุ่นได้โดยเปิดใช้งาน "การหารที่แท้จริง" ดังที่
Rob Dennis

110

หากทำงานกับจำนวนเต็มวิธีหนึ่งในการปัดเศษคือการใช้ประโยชน์จากความจริงที่//ปัดเศษลง: ทำการหารด้วยจำนวนลบแล้วคัดค้านคำตอบ ไม่มีการนำเข้าจุดลอยตัวหรือตามเงื่อนไขที่จำเป็น

rounded_up = -(-numerator // denominator)

ตัวอย่างเช่น:

>>> print(-(-101 // 5))
21

1
แล้วเมื่อคุณไม่ต้องทำการคำนวณทางคณิตศาสตร์ล่ะ นั่นคือคุณมีเพียงหมายเลขเดียว
คลิกที่

2
@Klik: จากนั้นคุณสามารถหารด้วย 1 ==> - (-num // 1) และคุณจะได้รับคำตอบ :-) ขอให้มีความสุขมาก ๆ ในวันนี้! David Bau: ข้อเสนอที่ดีมาก!
Marco smdm

10
ฉันหมดเวลาคำตอบทั้งหมดที่นี่และนี่เร็วกว่าคำว่าดีที่สุดลำดับถัดไป (math.ceil) ห้าเท่า @Andreas มีเวลาเดียวกัน
มินิ totent

@ minototent นั่นไม่น่าแปลกใจเพราะมันเป็นจำนวนเต็มหารง่าย ๆ และมีการทำงานแบบสองรอบเดียว นี่เป็นคำตอบที่ทำให้คุณได้งาน: การทำความเข้าใจไม่เพียง แต่ภาษา แต่เป็นเลเยอร์ของ abstractions ทั้งหมดข้างใต้
Nearoo

ดี! ฉันใช้อยู่เสมอ(num + den - 1) // denซึ่งเป็นสิ่งที่ดีสำหรับintอินพุตที่มีตัวหารเป็นบวก แต่ล้มเหลวถ้าแม้แต่ตัวที่ไม่รวมอินทิกรัลfloatก็มีส่วนเกี่ยวข้อง (ตัวเศษหรือส่วน) นี่เป็นรูปลักษณ์ที่มหัศจรรย์ยิ่งขึ้น แต่ใช้ได้ทั้งกับints และfloats สำหรับตัวเศษเล็ก ๆ มันก็เร็วขึ้น (ใน CPython 3.7.2) แม้ว่าจะผิดปกติ แต่เมื่อตัวเศษมีขนาดใหญ่พอที่จะต้องใช้คณิตศาสตร์แบบอาเรย์ ไม่ชัดเจนว่าทำไมถึงเป็นเช่นนี้เนื่องจากการแบ่งงานควรคล้ายกันและการปฏิเสธสองข้อที่ไม่ควรมีราคาถูกกว่าการบวก + การลบ
ShadowRanger

56

คุณอาจชอบ numpy:

>>> import numpy as np
>>> np.ceil(2.3)
3.0

ฉันไม่ได้บอกว่ามันดีไปกว่าคณิตศาสตร์ แต่ถ้าคุณใช้จำนวนมากเพื่อจุดประสงค์อื่นคุณสามารถทำให้โค้ดของคุณสอดคล้องกัน

อย่างไรก็ตามรายละเอียดที่ฉันเจอ ฉันใช้จำนวนมากและรู้สึกประหลาดใจที่ไม่ได้พูดถึง แต่แน่นอนว่าคำตอบที่ยอมรับนั้นใช้ได้ดีอย่างสมบูรณ์


3
การใช้ numpy ก็ดีเช่นกัน วิธีที่ง่ายที่สุดคือคณิตศาสตร์เพราะมันเป็นส่วนหนึ่งของหลามในห้องสมุด มันสมเหตุสมผลมากขึ้น แต่อย่างที่คุณพูดถึงถ้าคุณใช้จำนวนมากสำหรับปัญหาอื่น ๆ แล้วมันก็สมเหตุสมผลและสอดคล้องกับการใช้ numpy.ceil :-) คำใบ้ดี!
Marco smdm

30

ใช้math.ceilเพื่อปัดเศษขึ้น:

>>> import math
>>> math.ceil(5.4)
6.0

หมายเหตุ : อินพุตควรลอย

หากคุณต้องการจำนวนเต็มโทรintเพื่อแปลง:

>>> int(math.ceil(5.4))
6

BTW ใช้math.floorเพื่อปัดเศษลงและroundปัดเศษเป็นจำนวนเต็มที่ใกล้เคียงที่สุด

>>> math.floor(4.4), math.floor(4.5), math.floor(5.4), math.floor(5.5)
(4.0, 4.0, 5.0, 5.0)
>>> round(4.4), round(4.5), round(5.4), round(5.5)
(4.0, 5.0, 5.0, 6.0)
>>> math.ceil(4.4), math.ceil(4.5), math.ceil(5.4), math.ceil(5.5)
(5.0, 5.0, 6.0, 6.0)

1
อินพุตไม่จำเป็นต้องเป็นแบบลอยหากใช้ไพ ธ อน 3: ceil() จะดูแลข้อมูลภายใน
guival


11

ฉันประหลาดใจที่ไม่มีใครแนะนำ

(numerator + denominator - 1) // denominator

สำหรับการหารจำนวนเต็มด้วยการปัดเศษขึ้น เคยเป็นวิธีทั่วไปสำหรับ C / C ++ / CUDA (cf. divup)


2
เกี่ยวข้องเฉพาะกับภาษาที่พิมพ์แบบคงที่ หากตัวส่วนเป็นทุ่นคุณจะตาย
Bharel

สิ่งนี้จะทำงานได้อย่างต่อเนื่องหากตัวส่วนเป็นบวก หากตัวส่วนเป็นลบคุณต้องเพิ่ม1แทนการลบมันหรือพลิกสัญญาณของทั้งตัวเศษและส่วนก่อนที่จะทำการคำนวณ
ShadowRanger

7

เป็นค่าโค้งมน shure ควรจะลอย

a = 8 
b = 21
print math.ceil(a / b)
>>> 0

แต่

print math.ceil(float(a) / b)
>>> 1.0

6

ลองสิ่งนี้:

a = 211.0
print(int(a) + ((int(a) - a) != 0))

1
ฉลาด. การ((int(a) - a) != 0)แสดงออกกลับมา1เมื่อใดก็ตามที่aจะต้องปัดเศษขึ้น คุณอาจต้องการขยายคำตอบและอธิบายวิธีการทำงานของมัน
Tom Aranda

@TomAranda ทุกคนสามารถอธิบายได้อย่างไรว่านิพจน์บูลีนประเมินค่าได้อย่างไร
Bowen Liu

6
>>> def roundup(number):
...     return round(number+.5)
>>> roundup(2.3)
3
>>> roundup(19.00000000001)
20

ฟังก์ชั่นนี้ไม่ต้องใช้โมดูล


เกิดอะไรขึ้นถ้าหมายเลขของคุณเป็น3เช่นนั้นมันจะปัดเศษขึ้น4ซึ่งอาจเป็นหรืออาจไม่ใช่สิ่งที่ใครบางคนต้องการ
buydadip

15
ใช้งานได้ใน 99% ของทุกกรณีเท่านั้น คุณไม่ได้คิดอย่างนี้ โซลูชันดังกล่าวควรหลีกเลี่ยงค่าใช้จ่ายทั้งหมด
Nearoo

ดังนั้นแทนที่จะเป็น +.5 ทำ + .49999999 ดีพอสำหรับฉัน
FlyingZebra1

5

คำตอบข้างต้นนั้นถูกต้องอย่างไรก็ตามการนำเข้าmathโมดูลสำหรับฟังก์ชั่นนี้มักจะรู้สึกว่าเป็น overkill สำหรับฉัน โชคดีที่มีวิธีอื่นในการทำเช่นนี้:

g = 7/5
g = int(g) + (not g.is_integer())

TrueและFalseถูกตีความว่าเป็น1และ0ในคำสั่งที่เกี่ยวข้องกับตัวเลขในหลาม g.is_interger()โดยทั่วไปแปลว่าจะมีหรือg.has_no_decimal() g == int(g)ดังนั้นข้อความสุดท้ายในภาษาอังกฤษจึงอ่านround g down and add one if g has decimalได้


1
และถ้าคุณรู้สึกแฟนซีคุณสามารถใช้int(g) + (g % 1 > 0);-) แทนได้
Nearoo

from math import ceilดูเหมือนว่าจะแก้ไขการนำเข้าโมดูลคณิตศาสตร์ทั้งหมด :)
21414

@ SH7890 ฉันกลัวว่าบรรทัดจะไม่แตกต่างกันมากนักimport mathในแง่ของสิ่งที่เกิดขึ้นเบื้องหลัง ceilมันก็ลดลงสัญลักษณ์ทั้งหมดยกเว้น
Nearoo

5

โดยไม่ต้องนำเข้าคณิตศาสตร์ // ใช้ envionment ขั้นพื้นฐาน:

ก) วิธีการ / วิธีการเรียน

def ceil(fl): 
  return int(fl) + (1 if fl-int(fl) else 0)

def ceil(self, fl): 
  return int(fl) + (1 if fl-int(fl) else 0)

b) แลมบ์ดา:

ceil = lambda fl:int(fl)+(1 if fl-int(fl) else 0)

5

สำหรับผู้ที่ต้องการปัดเศษขึ้นa / bและรับจำนวนเต็ม:

ตัวแปรอื่นที่ใช้การหารจำนวนเต็มคือ

def int_ceil(a, b):
    return (a - 1) // b + 1

>>> int_ceil(19, 5)
4
>>> int_ceil(20, 5)
4
>>> int_ceil(21, 5)
5

3

ในกรณีที่ใครก็ตามที่ต้องการปัดเศษทศนิยมให้เจาะจง:

import math
def round_up(n, decimals=0):
    multiplier = 10 ** decimals
    return math.ceil(n * multiplier) / multiplier

1

ฉันประหลาดใจที่ฉันยังไม่เห็นคำตอบนี้round(x + 0.4999)ดังนั้นฉันจะวางมันลง โปรดทราบว่าสิ่งนี้ใช้ได้กับ Python ทุกรุ่น การเปลี่ยนแปลงรูปแบบการปัดเศษ Python ทำให้สิ่งต่างๆยากขึ้น ดูโพสต์นี้

ฉันจะใช้:

def roundUp(num):
    return round(num + 0.49)

testCases = list(x*0.1 for x in range(0, 50))

print(testCases)
for test in testCases:
    print("{:5.2f}  -> {:5.2f}".format(test, roundUp(test)))

ทำไมถึงได้ผล

จากเอกสาร

สำหรับประเภทในตัวที่สนับสนุนรอบ () ค่าจะถูกปัดเศษเป็นพหุคูณที่ใกล้เคียงที่สุดของ 10 ถึงกำลังไฟฟ้าลบ n; หากสองทวีคูณใกล้กันเท่ากันการปัดเศษจะไปทางเลือกคู่

ดังนั้น 2.5 จึงถูกปัดเศษเป็น 2 และ 3.5 ถูกปัดเศษเป็น 4 หากไม่เป็นเช่นนั้นการปัดเศษอาจทำได้โดยการเพิ่ม 0.5 แต่เราต้องการหลีกเลี่ยงการไปยังจุดกึ่งกลาง ดังนั้นถ้าคุณเพิ่ม 0.4999 คุณจะเข้าใกล้ แต่ด้วยระยะขอบที่มากพอที่จะถูกปัดเศษเป็นสิ่งที่คุณคาดหวัง แน่นอนว่าสิ่งนี้จะล้มเหลวหากx + 0.4999มีค่าเท่ากับ[n].5000แต่ไม่น่าเป็นไปได้


2
การใช้ 0.4999 มันจะล้มเหลวในการให้ผลลัพธ์ที่ถูกต้องสำหรับอินพุตใด ๆ ในระหว่าง ???. 0000 และ ???. 0001 (ช่วงเวลาเปิด) ไม่ใช่เพียงแค่ ???? 0001 ตัวอย่างเช่นหากคุณลองด้วย 3.00005 คุณจะได้รับผลลัพธ์เป็น 3 แทนที่จะเป็น 4 อย่างที่คาดไว้แน่นอนว่าคุณสามารถลดโอกาสในการเกิดเหตุการณ์นี้ได้โดยการเพิ่มตัวเลขมากขึ้นเรื่อย ๆ จนถึงความแม่นยำสูงสุดของการลอย ชี้ไปที่ถ้ามีโซลูชันที่แข็งแกร่งและใช้งานง่ายกว่าอยู่ในมือเช่นการใช้math.ceil()?
blubberdiblub

@blubberdiblub Without importing I use:ในรัฐคำตอบของผม ฉันได้กล่าวว่ามันจะล้มเหลวถ้ามีค่าเท่ากับx + 0.4999 [n].5000
Klik

4
ใช่คุณระบุไว้ในคำตอบของคุณว่าโซลูชันของคุณไม่มีการนำเข้า แต่ฉันไม่เห็นคุณค่าของมัน mathโมดูลและmath.ceil()อยู่ในห้องสมุดมาตรฐานที่มีอยู่เพื่อให้ทุกที่เพื่อประโยชน์โดยไม่ต้องมีการติดตั้งสิ่งที่พิเศษ และเกี่ยวกับการที่คุณพูดถึงเมื่อมันล้มเหลวมันไม่สมบูรณ์ในคำตอบของคุณเนื่องจากมันล้มเหลวตลอดช่วงเวลาไม่ใช่เพียงแค่จุดเดียว ในทางเทคนิคคุณสามารถโต้เถียงคุณว่าถูกต้องอย่างที่คุณพูดหากไม่ใช่iffแต่มันจะสร้างความประทับใจให้กับผู้อ่านทั่วไปที่มีโอกาสน้อยกว่าที่เป็นจริง
blubberdiblub

0

หากต้องการดำเนินการโดยไม่มีการนำเข้า:

>>> round_up = lambda num: int(num + 1) if int(num) != num else int(num)
>>> round_up(2.0)
2
>>> round_up(2.1)
3

0

ฉันรู้ว่าสิ่งนี้มาจากในขณะที่กลับ แต่ฉันพบคำตอบที่น่าสนใจดังนั้นที่นี่ไป:

-round(-x-0.5)

วิธีนี้จะช่วยแก้ไขกรณีและขอบสำหรับทั้งจำนวนบวกและลบและไม่ต้องการการนำเข้าฟังก์ชันใด ๆ

ไชโย


2
สิ่งนี้จะยังคงดำเนินต่อไป-round(-x-0.3) = x
Diblo Dk

0

เมื่อคุณใช้งาน 4500/1000 ในไพ ธ อนผลลัพธ์จะเป็น 4 เพราะสำหรับไพ ธ อนเริ่มต้นเป็นจำนวนเต็มผลลัพธ์จะมีเหตุผล: 4500/1000 = 4.5 -> int (4.5) = 4 และ ceil ของ 4 ชัดเจนเป็น 4

ใช้ 4500 / 1,000.0 ผลที่ได้คือ 4.5 และเพดาน 4.5 -> 5

การใช้จาวาสคริปต์คุณจะได้รับ 4.5 จาก 4500/1000 เนื่องจากจาวาสคริปต์จะใช้เฉพาะผลลัพธ์เป็น "ประเภทตัวเลข" และส่งกลับผลลัพธ์โดยตรงแบบลอย

โชคดี!!


นั่นเป็นเรื่องจริงใน Python 2.x เท่านั้น ใน Python 3 การหารด้วย Single /จะส่งผลให้เกิดการลอยดังนั้น4500/1000จะเป็น 4.5 เสมอ
Nearoo

0

หากคุณไม่ต้องการนำเข้าอะไรคุณสามารถเขียนฟังก์ชันง่าย ๆ ของคุณเองได้ดังนี้

def RoundUP(num): if num== int(num): return num return int(num + 1)


2
สิ่งนี้ใช้ไม่ได้ถ้า num เป็น 2.05 คุณต้องมีอย่างน้อยหลายหลักโดยมี 9 เป็นอินพุตของคุณทำให้คุณมี 0.999 ... ซึ่งก็คือ 1 แต่จากนั้นมุมกรณีที่ 2 ของคุณจะถูกปัดขึ้นอีกครั้ง - เอาล่ะฉันคิดว่ามันมีเหตุผลว่าทำไม math.ceil ถึงอยู่ตรงนั้น
โยฮันเนสมาเรียแฟรงก์

-1

คุณสามารถใช้การพัฒนาพื้นที่และเพิ่ม 1 เข้าไปได้ 2.3 // 2 + 1


2
หรือใช้ceil()แทนการทำสิ่งที่ตรงกันข้ามอย่างประหลาดและชดเชย
guival

2
สิ่งนี้ใช้ไม่ได้ ตัวอย่างเช่น:from math import ceil; assert 4 // 2 + 1 == ceil(4 / 2)
Carl Thomé

-1

ฉันคิดว่าคุณสับสนกลไกการทำงานระหว่างint()และround()และ

int()ตัดเลขทศนิยมทุกครั้งหากมีการกำหนดตัวเลขทศนิยม ในขณะที่round()ในกรณี2.5ที่2และ3อยู่ในระยะห่างเท่ากัน2.5Python จะคืนค่าใดก็ตามที่อยู่ห่างจากจุด 0 มากขึ้น

round(2.5) = 3
int(2.5) = 2

"การปัดเศษขึ้น" หมายความว่าเช่น2.3ได้รับการเปิด3ซึ่งเกิดขึ้นในทั้งสองตัวอย่างของคุณ
Nearoo

-2

แบ่งปันของฉัน

ฉันได้ทำการทดสอบแล้ว print(-(-101 // 5)) = 21ตัวอย่างที่ระบุด้านบนแล้ว

ตอนนี้สำหรับการปัดเศษขึ้น:

101 * 19% = 19.19

ฉันไม่สามารถใช้งานได้**ดังนั้นฉันจึงกระจายการคูณไปยังการหาร:

(-(-101 //(1/0.19))) = 20

-3

โดยทั่วไปฉันเป็นผู้เริ่มต้นที่ Python แต่ถ้าคุณเพียงแค่พยายามปัดเศษแทนทำไมไม่ทำ:

round(integer) + 1

2
สิ่งนี้จะไม่ทำงานสำหรับจำนวนเต็มใด ๆ ที่ 2.5 <จำนวนเต็ม <3 ค่าที่ต้องการหลังจากการปัดเศษขึ้นเป็น 3 แต่นิพจน์ของคุณจะเปลี่ยนเป็น 4
Pranav Shukla

1
ฉันคิดว่าคุณหมายความว่าround(integer + 0.5)นี่คือสิ่งที่ผมมักจะทำ
รีบ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.