가장 가까운 정수로 반올림


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

오류가 발생하지 않습니까? 기본 10을 가진 int ()에 대한 잘못된 리터럴 :
snh_nl

답변:


366
int(round(x))

반올림하고 정수로 바꿉니다.

편집하다:

변수에 int (round (h))를 할당하지 않았습니다. int (round (h))를 호출하면 정수를 반환하지만 다른 작업은 수행하지 않습니다. 그 줄을 다음과 같이 변경해야합니다.

h = int(round(h))

h에 새 값을 할당하려면

편집 2 :

의견에서 @plowman이 말했듯이 Python round()은 정상적으로 예상대로 작동하지 않으며 숫자가 변수로 저장되는 방식은 일반적으로 화면에 표시되는 방식이 아니기 때문입니다. 이 동작을 설명하는 많은 답변이 있습니다.

round ()가 올바르게 반올림되지 않는 것 같습니다

이 문제를 피하는 한 가지 방법은이 답변에 명시된 십진수를 사용하는 것입니다. https://stackoverflow.com/a/15398691/4345659

추가 라이브러리를 사용하지 않고이 답변이 제대로 작동하려면 사용자 정의 반올림 기능을 사용하는 것이 편리합니다. 많은 수정을 한 후 테스트 한 모든 저장 문제를 피할 수있는 다음 해결책을 생각해 냈습니다. repr()(NOT 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

여기서 dec10 점은 9가 될 수 있고- dec+1> 5보다 큰 숫자 인 경우 9는 0이되고 1은- dec-1번째 숫자 로 이동해야합니다 .

이를 고려하면 다음과 같은 이점이 있습니다.

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 ab의 연결에 초래되는 10후단 0 사라지는 곳에. 이 버전은 b을 기반으로 dec올바른 캐리로 올바른 소수점 이하 자릿수로 변환 됩니다 .


2
print ( "4.5)", int (round (4.5))) # 내게 4 print ( "5.5)", int (round (5.5))) # 내게 줘 6 :, (
Komm

파이썬 버전과 관련이 있습니다. 파이썬 2.7.9를 사용하여 5와 6을 제공합니다. 말씀하신 것처럼 파이썬 3.4.2를 사용하여 4와 6
francisco sollima

1
주목할만한 점 :이 솔루션은 예상대로 반올림되지 않습니다. 예를 들어, 5로 올림 int(round(4.5))하면서 4로 int(round(4.500001))내림합니다.
plowman

정수를 원한다면 round(x)파이썬 3.6.2 (그리고 아마도 더 낮은 버전)에서도 충분합니다. 결과는 이미 int 유형입니다. 참고 : round(x, n)float 유형입니다.
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반올림됩니다 (즉, 두 개의 10 진수로 반올림하면8.01 ). 부동 소수점 수학의 단점으로 인해 특정 값의 경우 대신 반올림됩니다!

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

아하! 이를 바탕으로 함수를 만들 수 있습니다 ...

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

기본적으로 이것은 사용하려는 문자열의 최소 숫자보다 작게 보장 된 값을 추가합니다 round. 소량을 추가하면 round대부분의 경우 동작을 유지 하면서 반올림되는 숫자보다 열등한 숫자가 반올림 5되는지 확인합니다.4 .

사용하는 접근 방식은 10**(-len(val)-1)시프트를 강제하기 위해 추가 할 수있는 가장 작은 숫자이므로 의도적으로 추가 .되었습니다. 또한 소수점 이하 자릿수 가 없어도 추가 한 값이 반올림을 변경하지 않도록합니다 . 더 많이 빼기 10**(-len(val))위해 조건부와 함께 사용할 수는 있지만 이 해결 방법으로 올바르게 처리 할 수있는 적용 가능한 10 진수 범위를 많이 변경하지 않으므로 항상 빼기하는 것이 더 간단합니다 . 이 방법은 값이 유형의 한계에 도달하면 실패하지만 실패하지만 거의 모든 유효 10 진수 값 범위에서 작동합니다.if (val>1)11

십진 라이브러리를 사용 하여이 작업을 수행 할 수도 있지만 제안하는 래퍼가 더 간단하고 경우에 따라 선호 될 수 있습니다.


편집 : 프린지 케이스가 특정 값에 대해서만 발생 한다고 지적한 Blckknght 에게 감사드립니다 5. 또한이 답변의 이전 버전은 반올림 하는 자리보다 숫자가 바로 열등한 경우에만5 홀수 반올림 동작이 발생 하기에 충분하지 않습니다 .


5마지막 자릿수가 항상 반올림되는 이유는 확실하지 않습니다 . 그건 내가처럼 숫자와 함께했던 빠른 테스트의 경우 아니에요 1.5, 2.5, 3.5등 및 1.05, 1.15, 1.25, 1.35소수 첫째 자리 반올림. 첫 번째 세트 (정확한 반올림을 작은 정수로 반올림)는 항상 짝수로 반올림합니다. 후자의 세트는 일부 값의 부정확 한 이진 표현으로 인해 일관되게 반올림되지 않습니다. 1.25round 와 같은 정확한 이진 표현을 가진 float는 가장 작은 자릿수를 갖지만 다른 것은 무작위로 반올림합니다.
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 및 바닥 추가"기술을 사용하지 마십시오. 예상 한대로 반올림하지 않을 수있는 값이 있습니다! C ++ 테이크에 대해서는 stackoverflow.com/a/47302585/2732969 를 참조하십시오 .이 질문에 대한 stackoverflow.com/a/38744026/2732969 답변입니다.
Anon

빠른 방법이 필요했고 정확하지 않아도되었고 많은 코너 사례가 없었으며 코너 시나리오의 오류는 시나리오에서 중요하지 않습니다. 따라서 이것은 속도가 최우선 인 특수한 경우를위한 것입니다. 정밀도 나 정확성을 권장하지 않습니다.
AgentM

11

IEEE 754에 규정 된대로 파이썬 만 반으로 반올림 하지 않습니까?

다시 정의하거나 "비표준"라운딩을 사용하십시오…

( https://stackoverflow.com/a/33019948/109839참조하십시오 )


2
이 답변은 약간 불분명합니다. Round half to evenIEEE 754에 의해 규정 된 것은 아니지만 표준에 의해 기술 된 몇 가지 반올림 옵션 중 하나 일뿐 입니다. Round to nearest, ties away from zero(즉, 대부분의 사람들이 기대하는 동작) 또한 옵션이며 C / C ++와 같은 기본값입니다.
tel

나는 그 말이 매우 혼란 스럽다는 것에 동의한다. 나는 파이썬 (의 끝 부분에있는 표 참조 heven 절반을 반올림 것이 무엇을 의미 docs.python.org/3.7/library/...round 처방 설명을)하고 "도에 라운드 절반"방법에 따라 이렇게됩니다 표준에 따라 작동 (또는 설명)합니다.
Mapio

8

python3.x를 사용하는 경우 numpy를 사용할 수도 있습니다. 여기에 예제가 있습니다.

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

https://docs.python.org/3/library/functions.html#round 의 Python 설명서에서

라운드 (숫자 [, n 자리])

소수점 뒤에 n 자리 정밀도로 반올림 된 숫자를 반환합니다. ndigits가 생략되거나 None이면 입력에 가장 가까운 정수를 반환합니다.

노트

float에 대한 round ()의 동작은 놀랍습니다. 예를 들어 round (2.675, 2)는 예상 2.68 대신 2.67을 제공합니다. 이것은 버그가 아닙니다. 대부분의 소수는 정확히 부동 소수점으로 표현할 수 없다는 사실의 결과입니다. 자세한 내용은 부동 소수점 산술 : 문제 및 제한 사항을 참조하십시오.


1

예를 들어 A에 대해 두 자리 근사값이 필요한 경우 int(A*100+0.5)/100.0원하는 것을 수행합니다.

세 자리 근사값이 필요한 경우 곱하여 1000으로 나눕니다.


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 (round (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.