Python 3.x 반올림 동작
방금 What's New In Python 3.0을 다시 읽었는데 다음과 같이 되어 있습니다.
round() 함수 반올림 전략과 반환 유형이 변경되었습니다.정확한 중간 케이스는 이제 0이 아닌 가장 가까운 짝수 결과로 반올림됩니다(예를 들어, 이제 라운드(2.5)는 3이 아니라 2를 반환합니다).
및 라운드용 문서:
라운드()를 지원하는 삽입형에서는 값이 10의 제곱에서 n을 뺀 배수에 가장 가까운 값으로 반올림됩니다.두 배수가 동등하게 가까우면 짝수 선택을 향해 반올림됩니다.
따라서 v2.7.3에서는 다음과 같습니다.
In [85]: round(2.5)
Out[85]: 3.0
In [86]: round(3.5)
Out[86]: 4.0
기대했던 대로요단, 현재 v3.2.3에서는 다음과 같이 되어 있습니다.
In [32]: round(2.5)
Out[32]: 2
In [33]: round(3.5)
Out[33]: 4
이것은 반직관적이고 반올림에 대해 제가 이해하고 있는 것과 반대되는 것 같습니다(그리고 사람들을 혼란스럽게 합니다).영어가 모국어는 아니지만, 이 글을 읽기 전까지는 반올림의 의미를 알고 있었다:-/ v3가 소개되었을 때, 이것에 대한 논의가 있었을 것이라고 확신하지만, 검색에서는 좋은 이유를 찾을 수 없었다.
- 이게 왜 이렇게 바뀌었는지 아는 사람 있나요?
- (나에게) 이런 종류의 반올림을 하는 다른 주류 프로그래밍 언어(예를 들어 C, C++, Java, Perl 등)가 있습니까?
내가 뭘 놓쳤지?
업데이트: @Li-aungYip의 코멘트 re "Banker's Rounding"을 통해 검색해야 할 올바른 검색어/키워드를 얻을 수 있었습니다.그리고 다음 질문을 찾았습니다.의 이유는 무엇입니까?NET에서는 뱅커 라운딩을 디폴트로 하고 있기 때문에, 그것을 주의 깊게 읽어 보겠습니다.
Python 3의 방식('반올림' 또는 '뱅커 반올림'이라고 함)은 현재 표준 반올림 방식으로 간주되고 있지만, 일부 언어 구현은 아직 버스에 제공되지 않았다.
단순한 「항상 반올림 0.5 업」테크놀로지에 의해, 높은 수치로 약간 치우치게 됩니다.계산 횟수가 많을 경우, 이는 매우 중요할 수 있습니다.Python 3.0 접근법은 이 문제를 해결합니다.
일반적으로 사용되는 반올림 방법에는 여러 가지가 있습니다.부동소수점 산술의 국제 표준인 IEEE 754는 5개의 다른 반올림 방법(Python 3.0에서 사용되는 방법이 기본값)을 정의합니다.그리고 다른 사람들도 있어요.
이런 행동은 그렇게 널리 알려져 있지 않다.AppleScript는, 제 기억이 맞다면, 이 반올림 방식의 얼리 어답터였습니다.AppleScript의 명령어는 몇 가지 옵션을 제공하지만 IEEE 754에서는 round-toward-even이 기본입니다.보아하니 이 시스템을 구현한 엔지니어는round
커맨드는, 「학교에서 배운 대로 동작하게 해 주세요」라고 하는 모든 요구에 싫증이 나서, 다음과 같이 실장했습니다.round 2.5 rounding as taught in school
는 유효한 AppleScript 명령어입니다. :- )
10진수 모듈을 사용하여 Py3000에서 얻을 수 있는 반올림을 제어할 수 있습니다.
>>> decimal.Decimal('3.5').quantize(decimal.Decimal('1'),
rounding=decimal.ROUND_HALF_UP)
>>> Decimal('4')
>>> decimal.Decimal('2.5').quantize(decimal.Decimal('1'),
rounding=decimal.ROUND_HALF_EVEN)
>>> Decimal('2')
>>> decimal.Decimal('3.5').quantize(decimal.Decimal('1'),
rounding=decimal.ROUND_HALF_DOWN)
>>> Decimal('3')
설명서에서 중요한 메모를 여기에 추가합니다.
https://docs.python.org/dev/library/functions.html#round
메모
플로트에 대한 round()의 동작은 놀라울 수 있습니다.예를 들어 round(2.675, 2)는 예상된 2.68이 아닌 2.67을 나타냅니다.이것은 버그가 아닙니다.대부분의 소수점이 플로트로 정확하게 표현되지 않기 때문입니다.부동 소수점 산술 참조:자세한 내용은 문제 및 제한사항을 참조하십시오.
따라서 Python 3.2에서 다음과 같은 결과를 얻는 것에 놀라지 마십시오.
>>> round(0.25,1), round(0.35,1), round(0.45,1), round(0.55,1)
(0.2, 0.3, 0.5, 0.6)
>>> round(0.025,2), round(0.035,2), round(0.045,2), round(0.055,2)
(0.03, 0.04, 0.04, 0.06)
Python 3.x는 0.5의 값을 네이버에 반올림하여
assert round(0.5) == 0
assert round(1.5) == 2
assert round(2.5) == 2
import decimal
assert decimal.Decimal('0.5').to_integral_value() == 0
assert decimal.Decimal('1.5').to_integral_value() == 2
assert decimal.Decimal('2.5').to_integral_value() == 2
단, 필요에 따라 소수 반올림 "back"을 항상 0.5 반올림하도록 변경할 수 있습니다.
decimal.getcontext().rounding = decimal.ROUND_HALF_UP
assert decimal.Decimal('0.5').to_integral_value() == 1
assert decimal.Decimal('1.5').to_integral_value() == 2
assert decimal.Decimal('2.5').to_integral_value() == 3
i = int(decimal.Decimal('2.5').to_integral_value()) # to get an int
assert i == 3
assert type(i) is int
저도 최근에 이런 문제가 있었어요.그 때문에, 이것을 다루고, 같은 반올림 동작을 하는 2개의 함수를 가지는 python 3 모듈을 개발했습니다(뱅크 라운딩이 아닙니다).여기 모듈이 있습니다.코드를 저장하고 복사하거나 가져오기만 하면 됩니다.주의: trueround_precision 모듈은 10진수 모듈의 ROUND_CEILING, ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_05UP 플래그에 따라 필요에 따라 반올림 동작을 변경할 수 있습니다(자세한 내용은 해당 모듈 참조).다음 함수에 대해서는 문서스트링을 참조해 주십시오.또한 설명서가 필요한 경우 도움말(트루라운드)과 도움말(트루라운드_precision)을 사용합니다.
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
def trueround(number, places=0):
'''
trueround(number, places)
example:
>>> trueround(2.55, 1) == 2.6
True
uses standard functions with no import to give "normal" behavior to
rounding so that trueround(2.5) == 3, trueround(3.5) == 4,
trueround(4.5) == 5, etc. Use with caution, however. This still has
the same problem with floating point math. The return object will
be type int if places=0 or a float if places=>1.
number is the floating point number needed rounding
places is the number of decimal places to round to with '0' as the
default which will actually return our interger. Otherwise, a
floating point will be returned to the given decimal place.
Note: Use trueround_precision() if true precision with
floats is needed
GPL 2.0
copywrite by Narnie Harshoe <signupnarnie@gmail.com>
'''
place = 10**(places)
rounded = (int(number*place + 0.5if number>=0 else -0.5))/place
if rounded == int(rounded):
rounded = int(rounded)
return rounded
def trueround_precision(number, places=0, rounding=None):
'''
trueround_precision(number, places, rounding=ROUND_HALF_UP)
Uses true precision for floating numbers using the 'decimal' module in
python and assumes the module has already been imported before calling
this function. The return object is of type Decimal.
All rounding options are available from the decimal module including
ROUND_CEILING, ROUND_DOWN, ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN,
ROUND_HALF_UP, ROUND_UP, and ROUND_05UP.
examples:
>>> trueround(2.5, 0) == Decimal('3')
True
>>> trueround(2.5, 0, ROUND_DOWN) == Decimal('2')
True
number is a floating point number or a string type containing a number on
on which to be acted.
places is the number of decimal places to round to with '0' as the default.
Note: if type float is passed as the first argument to the function, it
will first be converted to a str type for correct rounding.
GPL 2.0
copywrite by Narnie Harshoe <signupnarnie@gmail.com>
'''
from decimal import Decimal as dec
from decimal import ROUND_HALF_UP
from decimal import ROUND_CEILING
from decimal import ROUND_DOWN
from decimal import ROUND_FLOOR
from decimal import ROUND_HALF_DOWN
from decimal import ROUND_HALF_EVEN
from decimal import ROUND_UP
from decimal import ROUND_05UP
if type(number) == type(float()):
number = str(number)
if rounding == None:
rounding = ROUND_HALF_UP
place = '1.'
for i in range(places):
place = ''.join([place, '0'])
return dec(number).quantize(dec(place), rounding=rounding)
이게 도움이 됐으면 좋겠는데
나리
파이썬 3의 파이썬 2 반올림 동작.
소수점 15번째 자릿수에 1을 더합니다.최대 15자리 정확도
round2=lambda x,y=None: round(x+1e-15,y)
경우에 따라서는:
in: Decimal(75.29 / 2).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
in: round(75.29 / 2, 2)
out: 37.65 GOOD
in: Decimal(85.55 / 2).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
in: round(85.55 / 2, 2)
out: 42.77 BAD
수정의 경우:
in: round(75.29 / 2 + 0.00001, 2)
out: 37.65 GOOD
in: round(85.55 / 2 + 0.00001, 2)
out: 42.78 GOOD
소수점(예: 4)을 늘리려면 (+ 0.00001)을 추가해야 합니다.
날 위해 일해.
샘플 재생:
['{} => {}'.format(x+0.5, round(x+0.5)) for x in range(10)]
['0.5 => 0', '1.5 => 2', '2.5 => 2', '3.5 => 4', '4.5 => 4', '5.5 => 6', '6.5 => 6', '7.5 => 8', '8.5 => 8', '9.5 => 10']
API: https://docs.python.org/3/library/functions.html#round
상태:
소수점 뒤의 n자리 정밀도로 반올림된 반환 숫자입니다.ndigits가 생략되거나 None일 경우 입력에 가장 가까운 정수를 반환합니다.
삽입형 지지 라운드()의 경우, 값은 10의 제곱에서 n자릿수를 뺀 배수에 가장 가까운 값으로 반올림됩니다.두 배수가 동등하게 가까우면 짝수 선택을 향해 반올림됩니다(예를 들어 라운드(0.5)와 라운드(-0.5)는 모두 0, 라운드(1.5)는 2).임의의 정수 값은 n자리(양수, 0 또는 음수)에 대해 유효합니다.ndigits가 생략되거나 None일 경우 반환값은 정수입니다.그렇지 않은 경우 반환값은 번호와 동일한 유형을 가집니다.
일반적인 Python 개체 번호의 경우 number.round로 반올림합니다.
주의: 플로트에 대한 round()의 동작은 놀라울 수 있습니다.예를 들어 round(2.675, 2)는 예상된 2.68이 아닌 2.67을 나타냅니다.이것은 버그가 아닙니다.대부분의 소수점이 플로트로 정확하게 표현되지 않기 때문입니다.부동 소수점 산술 참조:자세한 내용은 문제 및 제한사항을 참조하십시오.
이 통찰력을 바탕으로 몇 가지 계산을 사용하여 해결할 수 있습니다.
import math
def my_round(i):
f = math.floor(i)
return f if i - f < 0.5 else f+1
이제 라운드 대신 my_round로 동일한 테스트를 실행할 수 있습니다.
['{} => {}'.format(x + 0.5, my_round(x+0.5)) for x in range(10)]
['0.5 => 1', '1.5 => 2', '2.5 => 3', '3.5 => 4', '4.5 => 5', '5.5 => 6', '6.5 => 7', '7.5 => 8', '8.5 => 9', '9.5 => 10']
# round module within numpy when decimal is X.5 will give desired (X+1)
import numpy as np
example_of_some_variable = 3.5
rounded_result_of_variable = np.round(example_of_some_variable,0)
print (rounded_result_of_variable)
다음 코드를 사용해 보십시오.
def roundup(input):
demo = input if str(input)[-1] != "5" else str(input).replace("5","6")
place = len(demo.split(".")[1])-1
return(round(float(demo),place))
결과는 다음과 같습니다.
>>> x = roundup(2.5)
>>> x
3.0
>>> x = roundup(2.05)
>>> x
2.1
>>> x = roundup(2.005)
>>> x
2.01
출력은 https://i.stack.imgur.com/QQUkS.png 에서 확인할 수 있습니다.
학교에서 배운 것처럼 Python 3.x에서 가장 쉽게 라운딩할 수 있는 방법은 보조 변수를 사용하는 것입니다.
n = 0.1
round(2.5 + n)
시리즈 2.0~3.0(0.1단계)의 결과는 다음과 같습니다.
>>> round(2 + n)
>>> 2
>>> round(2.1 + n)
>>> 2
>>> round(2.2 + n)
>>> 2
>>> round(2.3 + n)
>>> 2
>>> round(2.4 + n)
>>> 2
>>> round(2.5 + n)
>>> 3
>>> round(2.6 + n)
>>> 3
>>> round(2.7 + n)
>>> 3
>>> round(2.8 + n)
>>> 3
>>> round(2.9 + n)
>>> 3
>>> round(3 + n)
>>> 3
math.ceil 모듈을 사용하여 반올림을 제어할 수 있습니다.
import math
print(math.ceil(2.5))
> 3
언급URL : https://stackoverflow.com/questions/10825926/python-3-x-rounding-behavior
'programing' 카테고리의 다른 글
jQuery - 텍스트 설명을 통해 선택한 컨트롤의 값을 설정합니다. (0) | 2022.11.04 |
---|---|
Tomcat에서 Spring Boot를 시작할 때 사용자 이름과 비밀번호는 무엇입니까? (0) | 2022.10.26 |
JQuery - $가 정의되지 않았습니다. (0) | 2022.10.26 |
Python Maria DB 구문 (0) | 2022.10.26 |
열의 값이 값 집합 목록에 있는 경우 데이터 프레임 행 필터링 (0) | 2022.10.26 |