ปัดเศษเป็นจำนวนเต็มที่ใกล้ที่สุด


229

ฉันพยายามปัดเศษตัวเลขที่ยาวเช่น:

32.268907563;
32.268907563;
31.2396694215;
33.6206896552;
...

ยังไม่ประสบความสำเร็จ ฉันพยายามmath.ceil(x), math.floor(x)( แต่ที่จะปัดเศษขึ้นหรือลงซึ่งไม่ได้เป็นสิ่งที่ฉันกำลังมองหา) และround(x)ที่ไม่ได้ทำงานอย่างใดอย่างหนึ่ง (ยังคงลอยตัวเลข)

ฉันจะทำยังไงดี?

แก้ไข: รหัส:

for i in widthRange:
    for j in heightRange:
        r, g, b = rgb_im.getpixel((i, j))
        h, s, v = colorsys.rgb_to_hsv(r/255.0, g/255.0, b/255.0)
        h = h * 360
        int(round(h))
        print(h)

3
ฉันจะลองint(x)
The Brofessor

ที่จะไม่ให้ข้อผิดพลาด? ตัวอักษรที่ไม่ถูกต้องสำหรับ int () ที่มีฐาน 10:
snh_nl

คำตอบ:


366
int(round(x))

จะปัดเศษและเปลี่ยนเป็นจำนวนเต็ม

แก้ไข:

คุณไม่ได้กำหนด int (รอบ (h)) ให้กับตัวแปรใด ๆ เมื่อคุณโทรหา int (รอบ (h)) มันจะคืนค่าจำนวนเต็ม แต่ไม่ทำอะไรเลย คุณต้องเปลี่ยนบรรทัดสำหรับ:

h = int(round(h))

เพื่อกำหนดค่าใหม่ให้กับ h

แก้ไข 2:

ดังที่ @ plowman กล่าวไว้ในข้อคิดเห็นคอมไพ ธ อนround()ไม่ทำงานอย่างที่คาดหวังและนั่นเป็นเพราะวิธีการจัดเก็บหมายเลขเป็นตัวแปรมักไม่ใช่วิธีที่คุณเห็นบนหน้าจอ มีคำตอบมากมายที่อธิบายพฤติกรรมนี้:

round () ดูเหมือนจะไม่ปัดเศษอย่างเหมาะสม

วิธีหนึ่งในการหลีกเลี่ยงปัญหานี้คือการใช้ทศนิยมตามคำตอบนี้: https://stackoverflow.com/a/15398691/4345659

เพื่อให้คำตอบนี้ทำงานอย่างถูกต้องโดยไม่ต้องใช้ไลบรารีพิเศษมันจะสะดวกในการใช้ฟังก์ชันการปัดเศษที่กำหนดเอง หลังจากการแก้ไขมากมายฉันพบวิธีแก้ไขปัญหาต่อไปนี้ซึ่งเท่าที่ฉันทดสอบได้หลีกเลี่ยงปัญหาการจัดเก็บทั้งหมด มันขึ้นอยู่กับการใช้การเป็นตัวแทนสตริงที่ได้รับด้วยrepr()(ไม่str()!) มันดูแฮ็ค แต่มันเป็นวิธีเดียวที่ฉันค้นพบเพื่อแก้ไขทุกกรณี มันทำงานได้กับทั้ง Python2 และ Python3

def proper_round(num, dec=0):
    num = str(num)[:str(num).index('.')+dec+2]
    if num[-1]>='5':
        return float(num[:-2-(not dec)]+str(int(num[-2-(not dec)])+1))
    return float(num[:-1])

แบบทดสอบ:

>>> print(proper_round(1.0005,3))
1.001
>>> print(proper_round(2.0005,3))
2.001
>>> print(proper_round(3.0005,3))
3.001
>>> print(proper_round(4.0005,3))
4.001
>>> print(proper_round(5.0005,3))
5.001
>>> print(proper_round(1.005,2))
1.01
>>> print(proper_round(2.005,2))
2.01
>>> print(proper_round(3.005,2))
3.01
>>> print(proper_round(4.005,2))
4.01
>>> print(proper_round(5.005,2))
5.01
>>> print(proper_round(1.05,1))
1.1
>>> print(proper_round(2.05,1))
2.1
>>> print(proper_round(3.05,1))
3.1
>>> print(proper_round(4.05,1))
4.1
>>> print(proper_round(5.05,1))
5.1
>>> print(proper_round(1.5))
2.0
>>> print(proper_round(2.5))
3.0
>>> print(proper_round(3.5))
4.0
>>> print(proper_round(4.5))
5.0
>>> print(proper_round(5.5))
6.0
>>> 
>>> print(proper_round(1.000499999999,3))
1.0
>>> print(proper_round(2.000499999999,3))
2.0
>>> print(proper_round(3.000499999999,3))
3.0
>>> print(proper_round(4.000499999999,3))
4.0
>>> print(proper_round(5.000499999999,3))
5.0
>>> print(proper_round(1.00499999999,2))
1.0
>>> print(proper_round(2.00499999999,2))
2.0
>>> print(proper_round(3.00499999999,2))
3.0
>>> print(proper_round(4.00499999999,2))
4.0
>>> print(proper_round(5.00499999999,2))
5.0
>>> print(proper_round(1.0499999999,1))
1.0
>>> print(proper_round(2.0499999999,1))
2.0
>>> print(proper_round(3.0499999999,1))
3.0
>>> print(proper_round(4.0499999999,1))
4.0
>>> print(proper_round(5.0499999999,1))
5.0
>>> print(proper_round(1.499999999))
1.0
>>> print(proper_round(2.499999999))
2.0
>>> print(proper_round(3.499999999))
3.0
>>> print(proper_round(4.499999999))
4.0
>>> print(proper_round(5.499999999))
5.0

ในที่สุดคำตอบที่ถูกต้องจะเป็น:

# Having proper_round defined as previously stated
h = int(proper_round(h))

แก้ไข 3:

แบบทดสอบ:

>>> proper_round(6.39764125, 2)
6.31 # should be 6.4
>>> proper_round(6.9764125, 1)
6.1  # should be 7

gotcha ที่นี่คือที่decทศนิยม -th สามารถเป็น 9 และถ้าdec+1-th หลัก> = 5 9 จะกลายเป็น 0 และ 1 ควรจะดำเนินการกับตัวเลขdec-1-th

หากเราพิจารณาสิ่งนี้เราจะได้รับ:

def proper_round(num, dec=0):
    num = str(num)[:str(num).index('.')+dec+2]
    if num[-1]>='5':
      a = num[:-2-(not dec)]       # integer part
      b = int(num[-2-(not dec)])+1 # decimal part
      return float(a)+b**(-dec+1) if a and b == 10 else float(a+str(b))
    return float(num[:-1])

ในสถานการณ์ที่อธิบายข้างต้นb = 10และรุ่นก่อนหน้านี้ก็จะ concatenate aและbซึ่งจะส่งผลในการเรียงต่อกันของ10ที่ต่อท้าย 0 จะหายไป รุ่นนี้แปลงbเป็นตำแหน่งทศนิยมที่ถูกต้องตามdecความเหมาะสม


2
พิมพ์ ("4.5)", int (รอบ (4.5))) # ให้ฉัน 4 พิมพ์ ("5.5)", int (รอบ (5.5))) # ให้ฉัน 6
:,

มันเกี่ยวข้องกับเวอร์ชั่น Python มันให้ฉัน 5 และ 6 ใช้ Python 2.7.9 และอย่างที่คุณบอก, 4 และ 6 ใช้ Python 3.4.2
francisco sollima

1
เร็ว ๆ นี้: วิธีนี้ไม่ได้เป็นไปตามที่คุณคาดหวัง ตัวอย่างเช่นint(round(4.5))ปัดเศษลงเป็น 4 ในขณะที่int(round(4.500001))ปัดเศษเป็น 5 อย่างถูกต้อง
ไถนา

ถ้าคุณต้องการจำนวนเต็มก็round(x)เพียงพอแล้วใน Python 3.6.2 (และอาจต่ำกว่าด้วย) ผลลัพธ์มีประเภท int อยู่แล้ว หมายเหตุ: round(x, n)จะเป็นประเภทลอย
Elmex80s

1
สิ่งนี้ใช้ไม่ได้กับ 112439.50093565206 มันให้ o / p -> 11253.0 พิลึกพิลึก .. !!!!
ajin

24

round(x, y)ใช้ มันจะปัดเศษตัวเลขขึ้นเป็นทศนิยมที่คุณต้องการ

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

>>> round(32.268907563, 3)
32.269

20

round(value,significantDigit)เป็นทางออกที่ธรรมดา 5แต่นี้ไม่สามารถทำงานได้เป็นหนึ่งคาดหวังจากมุมมองทางคณิตศาสตร์เมื่อค่ารอบในตอนจบ หากตัวเลข5อยู่ในหน่วยหลักหลังจากที่คุณปัดเศษค่าเหล่านี้จะถูกปัดเศษขึ้นตามที่คาดไว้ (เช่น8.005การปัดเศษให้เป็นทศนิยมสองหลัก8.01) สำหรับค่าบางค่าเนื่องจาก quirks ของคณิตศาสตร์จุดลอยพวกเขาจะถูกปัดเศษลงแทน!

กล่าวคือ

>>> round(1.0005,3)
1.0
>>> round(2.0005,3)
2.001
>>> round(3.0005,3)
3.001
>>> round(4.0005,3)
4.0
>>> round(1.005,2)
1.0
>>> round(5.005,2)
5.0
>>> round(6.005,2)
6.0
>>> round(7.005,2)
7.0
>>> round(3.005,2)
3.0
>>> round(8.005,2)
8.01

แปลก.

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

>>> round(0.075,2)

0.07

>>> round(0.075+10**(-2*5),2)

0.08

Aha! จากนี้เราสามารถสร้างฟังก์ชัน ...

def roundTraditional(val,digits):
   return round(val+10**(-len(str(val))-1), digits)

โดยทั่วไปนี้จะเพิ่มมูลค่าที่รับประกันว่าจะมีขนาดเล็กกว่าบาทให้น้อยที่สุดของสตริงที่คุณกำลังพยายามที่จะใช้roundในการ โดยการเพิ่มจำนวนเล็กน้อยนั้นจะรักษาroundพฤติกรรมของในกรณีส่วนใหญ่ในขณะที่ตอนนี้มั่นใจได้ว่าตัวเลขที่ต่ำกว่าตัวเลขที่ถูกปัดเศษเป็น5มันปัดเศษขึ้นและถ้า4มันปัดเศษลง

วิธีการใช้10**(-len(val)-1)นั้นมีความรอบคอบเนื่องจากเป็นจำนวนน้อยที่สุดที่คุณสามารถเพิ่มเพื่อบังคับให้เปลี่ยนได้ในขณะที่ยังมั่นใจได้ว่าค่าที่คุณเพิ่มจะไม่เปลี่ยนการปัดเศษแม้ว่าทศนิยม.จะหายไป ฉันสามารถใช้เพียงแค่10**(-len(val))มีเงื่อนไขif (val>1)เพื่อลบ1มากกว่า ... แต่มันง่ายกว่าที่จะลบเสมอ1เพราะมันจะไม่เปลี่ยนช่วงจำนวนทศนิยมที่ใช้บังคับวิธีแก้ปัญหานี้สามารถจัดการได้อย่างถูกต้อง วิธีการนี้จะล้มเหลวหากค่าของคุณถึงขีด จำกัด ของประเภทนี้จะล้มเหลว แต่สำหรับเกือบทุกช่วงของค่าทศนิยมที่ถูกต้องที่ควรใช้

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


แก้ไข:ขอบคุณBlckknghtสำหรับการชี้ให้เห็นว่า5กรณีขอบเกิดขึ้นเฉพาะค่าที่แน่นอน รุ่นก่อนหน้าของคำตอบนี้ยังไม่ชัดเจนเพียงพอว่าพฤติกรรมการปัดเศษแปลกเกิดขึ้นเฉพาะในกรณีที่ตัวเลขนั้นต่ำกว่าตัวเลขที่คุณปัดเศษขึ้นใน5ทันที


ฉันไม่แน่ใจว่าทำไมคุณถึงคิดว่าทศนิยม5เป็นหลักสุดท้ายของพวกเขาจะถูกปัดเศษลงเสมอ กรณีที่ไม่อยู่ในการทดสอบอย่างรวดเร็วผมก็ไม่ได้มีตัวเลขเช่น1.5, 2.5, 3.5และอื่น ๆ และ1.05, 1.15, 1.25, 1.35ปัดเศษทศนิยมหนึ่งตำแหน่ง ชุดแรก (แบ่งครึ่งที่แน่นอนเป็นจำนวนเต็มเล็กน้อย) จะปัดเศษเป็นจำนวนเต็มคู่เสมอ ชุดหลังไม่ปัดอย่างสม่ำเสมออาจเนื่องมาจากการแทนค่าไบนารีที่ไม่แน่นอนของค่าบางค่า การลอยที่มีการแทนเลขฐานสองที่แน่นอนเช่น1.25รอบที่จะมีหลักสำคัญน้อยที่สุด แต่คนอื่น ๆ ที่ดูเหมือนจะสุ่มรอบ
Blckknght

น่าสนใจ ... คุณพูดถูก round(4.0005,3)ให้4.0และround(1.0005,3)ให้1.0แต่round(2.0005,3)ให้2.001และ จะช่วยให้round(3.0005,3) 3.001แต่นั่นเป็นเหตุผลว่าทำไมการแก้ปัญหาที่เสนอของฉันจึงเป็นสิ่งจำเป็น ... คุณไม่รู้ว่าจะคาดหวังอะไรจากรอบสต็อกในกรณีสำคัญนี้!
Jason R. Mick

ขอบคุณสำหรับสิ่งนี้. ฟังก์ชั่นของคุณจะมีประโยชน์เมื่อเกิดปัญหานี้ขึ้น
TMWP

1
คุณหมายถึงมี, digitsคำสั่งส่งคืนหรือไม่? เล่นสำนวนไม่มีเจตนา ( หมายถึงฉันหมายถึง)
user3342816

อาถูกต้องแน่นอนที่ควรจะอยู่ในนั้น จับได้ดี ... ประหลาดใจที่ไม่มีใครสังเกตเห็น! จะช่วยผู้ที่ใช้วิธีแก้ปัญหาความคับข้องใจบางอย่าง :-)
Jason R. Mick

15

สำหรับผลบวกลอง

int(x + 0.5)

เพื่อให้มันใช้ได้กับเนกาทีฟด้วยลอง

int(x + (0.5 if x > 0 else -0.5))

int()ทำงานเหมือนฟังก์ชันพื้นและด้วยเหตุนี้คุณจึงสามารถใช้ประโยชน์จากคุณสมบัตินี้ได้ นี่เป็นวิธีที่เร็วที่สุดแน่นอน


4
ไม่ทำงานสำหรับเชิงลบ>>> x=-0.999 >>> int(x), round(x), int(x+0.5) (0, -1.0, 0)
user2907934

3
หากคุณสนใจกรณีมุมไม่ใช้เทคนิค "เพิ่ม 0.5 และพื้น" - มีค่าบางอย่างที่อาจไม่เป็นไปตามที่คุณคาดหวัง! ดูstackoverflow.com/a/47302585/2732969สำหรับการใช้ C ++ และstackoverflow.com/a/38744026/2732969คำตอบสำหรับคำถามนี้
Anon

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

11

Python ไม่เพียงแค่ทำครึ่งรอบถึงแม้จะเป็นไปตามที่กำหนดโดยIEEE 754 ?

ระวังการกำหนดใหม่หรือใช้การปัดเศษ "ที่ไม่ได้มาตรฐาน" ...

(ดูที่https://stackoverflow.com/a/33019948/109839 )


2
คำตอบนี้ไม่ชัดเจน Round half to evenถูกอย่างไม่กำหนดโดย IEEE 754 แต่แทนที่จะเป็นเพียงหนึ่งในตัวเลือกการปัดเศษหลายอธิบายโดยมาตรฐาน Round to nearest, ties away from zero(เช่นพฤติกรรมที่คนส่วนใหญ่คาดหวัง) ก็เป็นตัวเลือกเช่นกันและเป็นค่าเริ่มต้นเช่น C / C ++
โทร

ฉันเห็นด้วยถ้อยคำค่อนข้างสับสน สิ่งที่ฉันหมายความว่า Python กำลังปัดครึ่งถึงสิบเอ็ด (ดูตารางท้ายdocs.python.org/3.7/library/ …ที่roundมีการอธิบาย) และมันทำตามวิธีการที่กำหนด "รอบครึ่งถึง" ในการทำงาน (หรืออธิบาย) ตามมาตรฐาน
Mapio

8

คุณยังสามารถใช้ numpy สมมติว่าคุณกำลังใช้ python3.x นี่คือตัวอย่าง

import numpy as np
x = 2.3
print(np.rint(x))
>>> 2.0

7

โซลูชันของคุณกำลังโทรหาโดยไม่ระบุอาร์กิวเมนต์ที่สอง (จำนวนตำแหน่งทศนิยม)

>>> round(0.44)
0
>>> round(0.64)
1

ซึ่งเป็นผลลัพธ์ที่ดีกว่า

>>> int(round(0.44, 2))
0
>>> int(round(0.64, 2))
0

จากเอกสาร Python ที่https://docs.python.org/3/library/functions.html#round

รอบ (หมายเลข [, ndigits])

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

บันทึก

พฤติกรรมของ round () สำหรับ floats นั้นน่าประหลาดใจตัวอย่างเช่น round (2.675, 2) ให้ 2.67 แทนที่จะเป็น 2.68 ที่คาดไว้ นี่ไม่ใช่ข้อผิดพลาด: เป็นผลมาจากความจริงที่ว่าเศษส่วนทศนิยมส่วนใหญ่ไม่สามารถแสดงได้ว่าเป็นทศนิยม ดูคณิตศาสตร์เลขทศนิยม: ประเด็นและข้อ จำกัด สำหรับข้อมูลเพิ่มเติม


1

หากคุณต้องการ (ตัวอย่าง) ประมาณสองหลักสำหรับ A จากนั้น int(A*100+0.5)/100.0จะทำสิ่งที่คุณกำลังมองหา

หากคุณต้องการการประมาณสามหลักคูณและหารด้วย 1,000 และต่อไป


1

บางสิ่งเช่นนี้ควรทำงานได้เช่นกัน

import numpy as np    

def proper_round(a):
    '''
    given any real number 'a' returns an integer closest to 'a'
    '''
    a_ceil = np.ceil(a)
    a_floor = np.floor(a)
    if np.abs(a_ceil - a) < np.abs(a_floor - a):
        return int(a_ceil)
    else:
        return int(a_floor)

0

เพื่อจุดประสงค์นี้ฉันขอแนะนำให้ทำสิ่งต่อไปนี้ -

int(round(x))

สิ่งนี้จะทำให้คุณเป็นจำนวนเต็มที่ใกล้ที่สุด

หวังว่านี่จะช่วยได้ !!


0

ฉันใช้และอาจแนะนำวิธีแก้ปัญหาต่อไปนี้ (python3.6):

y = int(x + (x % (1 if x >= 0 else -1)))

มันทำงานได้ดีสำหรับตัวเลขครึ่งหนึ่ง (บวกและลบ) และทำงานได้เร็วกว่า int (รอบ (x)):

round_methods = [lambda x: int(round(x)), 
                 lambda x: int(x + (x % (1 if x >= 0 else -1))),
                 lambda x: np.rint(x).astype(int),
                 lambda x: int(proper_round(x))]

for rm in round_methods:
    %timeit rm(112.5)
Out:
201 ns ± 3.96 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
159 ns ± 0.646 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
925 ns ± 7.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
1.18 µs ± 8.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

for rm in round_methods:
    print(rm(112.4), rm(112.5), rm(112.6))
    print(rm(-12.4), rm(-12.5), rm(-12.6))
    print('=' * 11)

Out:
112 112 113
-12 -12 -13
===========
112 113 113
-12 -13 -13
===========
112 112 113
-12 -12 -13
===========
112 113 113
-12 -13 -13
===========
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.