13.95a
로 반올림 하고 싶습니다 .
>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999
round
기능은 내가 예상대로 작동하지 않습니다.
13.95a
로 반올림 하고 싶습니다 .
>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999
round
기능은 내가 예상대로 작동하지 않습니다.
답변:
부동 소수점 숫자와 관련된 오래된 문제 가 발생 하여 모든 숫자를 정확하게 표현할 수는 없습니다. 명령 행은 메모리의 전체 부동 소수점 형식을 보여줍니다.
부동 소수점 표현의 경우 둥근 버전은 같은 숫자입니다. 컴퓨터는 이진이므로 부동 소수점 숫자를 정수로 저장 한 다음 2의 거듭 제곱으로 나눕니다. 따라서 13.95는 125650429603636838 / (2 ** 53)과 비슷한 방식으로 나타납니다.
배정도 숫자의 정밀도는 53 비트 (16 자리)이고 일반 부동 소수점의 정밀도는 24 비트 (8 자리)입니다. Python 의 부동 소수점 유형은 배정 밀도 를 사용하여 값을 저장합니다.
예를 들어
>>> 125650429603636838/(2**53)
13.949999999999999
>>> 234042163/(2**24)
13.949999988079071
>>> a = 13.946
>>> print(a)
13.946
>>> print("%.2f" % a)
13.95
>>> round(a,2)
13.949999999999999
>>> print("%.2f" % round(a, 2))
13.95
>>> print("{:.2f}".format(a))
13.95
>>> print("{:.2f}".format(round(a, 2)))
13.95
>>> print("{:.15f}".format(round(a, 2)))
13.949999999999999
예를 들어 통화 값을 표시하기 위해 소수점 이하 두 자리 만 뒤에 있으면 몇 가지 더 나은 선택이 있습니다.
"%.2f" % round(a,2)
당신은 printf뿐만 아니라 다음과 같은 것들에 넣을 수 있다고 언급 할 가치가 있습니다.str()
float
)은 10 진수의 가장 근접한 근사치 라는 것을 이해해야합니다 . 0.245와 같은 (유일하게 표현 가능한) 이진 값은 없습니다. 단순히 존재하지 않으며 수학적으로 존재할 수 없습니다 . 0.245에 가장 가까운 이진 값은 0.245 보다 약간 작 으므로 자연스럽게 내림합니다. 마찬가지로 이진에는 0.225와 같은 것은 없지만 0.225에 가장 가까운 이진 값은 0.225 보다 약간 크므로 자연스럽게 반올림됩니다.
Decimal
답변에 제시된 솔루션 중 하나였습니다. 다른 하나는 수량을 정수로 변환하고 정수 산술을 사용하는 것입니다. 이 두 가지 접근 방식은 다른 답변과 의견에도 등장했습니다.
새로운 형식 사양 인 String Format Specification Mini-Language가 있습니다 .
다음과 같은 작업을 수행 할 수 있습니다.
"{:.2f}".format(13.949999999999999)
참고 1 : 위는 문자열을 반환합니다. 플로트로 사용하려면 다음과 같이 간단히 랩핑하십시오 float(...)
.
float("{:.2f}".format(13.949999999999999))
참고 2 : 줄 바꿈 float()
해도 아무런 변화가 없습니다.
>>> x = 13.949999999999999999
>>> x
13.95
>>> g = float("{:.2f}".format(x))
>>> g
13.95
>>> x == g
True
>>> h = round(x, 2)
>>> h
13.95
>>> x == h
True
'{0:,.2f}'.format(1333.949999999)
인쇄 할 수 있습니다 '1,333.95'
.
float()
. float("{0:.2f}".format(13.9499999))
f"Result is {result:.2f}"
round(2.16, 1)
알려 2.2
truncate
>>> round(2.675, 2) 2.67
docs.python.org/2/tutorial/floatingpoint.html
Note The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float.
가장 간단한 방법은 format()
기능 을 사용하는 것입니다.
예를 들면 다음과 같습니다.
a = 13.949999999999999
format(a, '.2f')
13.95
이것은 소수점 이하 두 자리로 반올림 된 문자열로 부동 숫자를 생성합니다.
사용하다
print"{:.2f}".format(a)
대신에
print"{0:.2f}".format(a)
후자는 여러 변수를 출력하려고 할 때 출력 오류가 발생할 수 있기 때문에 (주석 참조).
대부분의 숫자는 실수로 정확하게 표현 될 수 없습니다. 수학 공식이나 알고리즘에 필요한 숫자이므로 숫자를 반올림하려면 반올림을 사용하십시오. 디스플레이를 특정 정밀도로 제한하려면 round를 사용하지 않고 해당 문자열로 형식화하십시오. (일부 대체 반올림 방법으로 표시하려는 경우 톤이 많은 경우 두 가지 방법을 혼합해야합니다.)
>>> "%.2f" % 3.14159
'3.14'
>>> "%.2f" % 13.9499999
'13.95'
마지막으로, 아마도 가장 중요하지만 정확한 수학을 원한다면 수레를 원하지 않습니다. 일반적인 예는 돈을 다루고 '센트'를 정수로 저장하는 것입니다.
아래 코드를 사용해보십시오 :
>>> a = 0.99334
>>> a = int((a * 100) + 0.5) / 100.0 # Adding 0.5 rounds it up
>>> print a
0.99
round
처음에 함수를 사용하는 것 보다이 작업을 수행하는 것에는 이점이 없습니다 . 다른 말로,이 솔루션은 여전히 부동 소수점을 사용하기 때문에이 "솔루션"의 "수정 된"버전에서도 OP의 원래 문제는 남아 있습니다.
round
(질문에 사용 된) 함수 의 불필요한 재 구현입니다 .
round()
는 OP가 언급 한대로 작동하지 않으면 필요합니다 .
입 / 출력의 반올림 문제는 Python 2.7.0 및 3.1에 의해 결정적 으로 해결 되었습니다 .
올바르게 반올림 된 숫자는 가역적으로 앞뒤로 변환 될 수 있습니다.
str -> float() -> repr() -> float() ...
또는 Decimal -> float -> str -> Decimal
더 이상 10 진수 유형이 저장에 필요하지 않습니다.
(자연스럽게, 누적 된 마지막 비트 오류를 제거하기 위해 반올림 된 숫자의 덧셈 또는 뺄셈 결과를 반올림해야 할 수도 있습니다. 명시 적 십진 산술은 여전히 유용 할 수 있지만 문자열을 str()
(12 개의 유효한 숫자로 반올림하여) )는 극단적 인 정확도가 없거나 극도의 연속적인 산술 연산이 필요하지 않은 경우 일반적으로 충분합니다.)
무한 테스트 :
import random
from decimal import Decimal
for x in iter(random.random, None): # Verify FOREVER that rounding is fixed :-)
assert float(repr(x)) == x # Reversible repr() conversion.
assert float(Decimal(repr(x))) == x
assert len(repr(round(x, 10))) <= 12 # Smart decimal places in repr() after round.
if x >= 0.1: # Implicit rounding to 12 significant digits
assert str(x) == repr(round(x, 12)) # by str() is good enough for small errors.
y = 1000 * x # Decimal type is excessive for shopping
assert str(y) == repr(round(y, 12 - 3)) # in a supermaket with Python 2.7+ :-)
참조 다른 언어 변경 - 릴리스 파이썬은 2.7을 노트 : 네 번째 단락을
대부분의 플랫폼 에서 부동 소수점 숫자와 문자열 간의 변환 이 올바르게 반올림 됩니다. 이러한 변환은 여러 다른 위치에서 발생합니다. float (float) 및 복소수의 str (); float 및 complex 생성자; 숫자 형식; 직렬화 및 사용 바늘 및 복소수 디 직렬화
marshal
,pickle
및json
모듈; 파이썬 코드에서 부동 및 허수 리터럴 파싱; 및 소수에서 부동으로의 변환.이와 관련하여 부동 소수점 숫자 x 의 repr () 은 이제 올바른 반올림 하에서 x 로 반올림 되는 것이 보장 되는 가장 짧은 10 진수 문자열을 기반으로 결과를 반환합니다 (반올림에서 반올림 모드로). 이전에는 x를 십진수 17로 반올림하여 문자열을 제공했습니다.
추가 정보 :float
Python 2.7 이전 의 형식은 current와 유사합니다 numpy.float64
. 두 유형 모두 52 비트 가수와 동일한 64 비트 IEEE 754 배정 밀도를 사용합니다 . 큰 차이는 np.float64.__repr__
비트가 손실되지 않도록 과도한 10 진수로 자주 포맷되지만 13.949999999999999와 13.950000000000001 사이에 유효한 IEEE 754 번호가 없다는 것입니다. 결과는 좋지 않으며 repr(float(number_as_string))
numpy로 변환을 되돌릴 수 없습니다. 반면에 :float.__repr__
모든 숫자가 중요하도록 형식이 지정됩니다. 순서는 틈이 없으며 변환은 되돌릴 수 있습니다. 간단히 : 아마도 numpy.float64 숫자가 있다면 숫자 프로세서가 아닌 사람을 위해 형식화되도록 일반 float로 변환하십시오. 그렇지 않으면 Python 2.7 이상에서는 더 이상 필요하지 않습니다.
float
(배정 밀도) 및 normal round
에 관한 것입니다. 일반 Python 반올림은 실제로 Python 2.7보다 더 잘 수행 할 수 없습니다. 대부분의 답변은 2.7 이전에 작성되었지만 원래는 훌륭했지만 더 이상 사용되지 않습니다. 이것이 내 대답의 이유입니다.
1
"점진적 언더 플로"를 제외하고 암시 적으로 "숨겨진 비트"를 포함 할 때 53 비트 .
a*b
대 b*a
. 링크-노스탤지어에 감사드립니다.
Python <3 (예 : 2.6 또는 2.7)에서는 두 가지 방법이 있습니다.
# Option one
older_method_string = "%.9f" % numvar
# Option two (note ':' before the '.9f')
newer_method_string = "{:.9f}".format(numvar)
그러나 3 이상의 Python 버전 (예 : 3.2 또는 3.3)의 경우 옵션 2가 선호 됩니다.
옵션 2에 대한 자세한 내용 은 Python 설명서의 문자열 형식 에 대한 링크를 제안합니다 .
옵션 1에 대한 자세한 정보는 이 링크로 충분하고 다양한 플래그에 대한 정보가 있습니다.
numvar=12.456
, "{:.2f}".format(numvar)
산출 12.46
하지만 "{:2i}".format(numvar)
오류가 발생하고 기대 12
합니다.
파이썬에서 format 연산자를 사용 하여 소수점 이하 2 자리까지 값을 반올림 할 수 있습니다 .
print(format(14.4499923, '.2f')) // output is 14.45
파이썬 2.7에서 :
a = 13.949999999999999
output = float("%0.2f"%a)
print output
output
와 정확히 같은 값을 가지 a
므로 마지막 줄 print a
대신에 쓸 수도 있습니다 print output
.
13.95
됩니다. 그러나 파이썬 2.7에서는 print a
이 특정 값에 대해서도 a
마찬가지이므로 서식 지정 단계의 요점이 무엇인지 명확하지 않습니다.
a == output
표시하는 코드를 사용해 보셨습니까 ? 그것은 True
나에게도 도움이되며, 당신에게도 그렇게 생각합니다.
Python 자습서에는 부동 소수점 산술 : 문제 및 제한 사항 이라는 부록이 있습니다. 읽어. 무슨 일이 일어나고 왜 파이썬이 최선을 다하는지 설명합니다. 그것은 당신과 일치하는 예를 가지고 있습니다. 조금 인용하겠습니다 :
>>> 0.1 0.10000000000000001
이
round()
기능 을 사용하여 원하는 한 자리수로 다시 자르 려고 할 수도 있습니다 . 그러나 그것은 아무런 차이가 없습니다.>>> round(0.1, 1) 0.10000000000000001
문제는에 대해 저장된 이진 부동 소수점 값
“0.1”
이 이미 가장 좋은 이진 근사치라는 것입니다.1/10
이므로 다시 반올림해도 더 나아질 수는 없습니다. 이미 얻는 것만 큼 좋았습니다.또 다른 결과는
0.1
정확히 아니기 때문에1/10
10 개의 값을0.1
합하면 정확히 산출하지 못할 수도1.0
있습니다.>>> sum = 0.0 >>> for i in range(10): ... sum += 0.1 ... >>> sum 0.99999999999999989
문제에 대한 대안과 해결책은 decimal
모듈을 사용하는 것 입니다.
Python 및 JavaScript와 같은 유형 동적 언어에서 부동 소수점을 수정하기 위해이 기술을 사용합니다.
# For example:
a = 70000
b = 0.14
c = a * b
print c # Prints 980.0000000002
# Try to fix
c = int(c * 10000)/100000
print c # Prints 980
다음과 같이 Decimal을 사용할 수도 있습니다.
from decimal import *
getcontext().prec = 6
Decimal(1) / Decimal(7)
# Results in 6 precision -> Decimal('0.142857')
getcontext().prec = 28
Decimal(1) / Decimal(7)
# Results in 28 precision -> Decimal('0.1428571428571428571428571429')
getcontext().prec = 6
기능의 범위 또는 모든 장소에서 작동합니까?
from decimal import Decimal
def round_float(v, ndigits=2, rt_str=False):
d = Decimal(v)
v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits))
if rt_str:
return v_str
return Decimal(v_str)
결과 :
Python 3.6.1 (default, Dec 11 2018, 17:41:10)
>>> round_float(3.1415926)
Decimal('3.14')
>>> round_float(3.1445926)
Decimal('3.14')
>>> round_float(3.1455926)
Decimal('3.15')
>>> round_float(3.1455926, rt_str=True)
'3.15'
>>> str(round_float(3.1455926))
'3.15'
다음과 같은 람다 함수는 어떻습니까?
arred = lambda x,n : x*(10**n)//1/(10**n)
이렇게하면 그냥 할 수 있습니다 :
arred(3.141591657,2)
그리고 얻다
3.14
1,2,3과 같이 간단합니다.
십진수를 사용하십시오빠르고 정확하게 반올림 된 소수점 부동 소수점 산술을 모듈을 .
d = 소수 (10000000.0000009)
반올림을 달성하려면 :
d.quantize(Decimal('0.01'))
와 결과 Decimal('10000000.00')
def round_decimal(number, exponent='0.01'):
decimal_value = Decimal(number)
return decimal_value.quantize(Decimal(exponent))
또는
def round_decimal(number, decimal_places=2):
decimal_value = Decimal(number)
return decimal_value.quantize(Decimal(10) ** -decimal_places)
추신 : 다른 사람들의 비판 : 형식이 반올림되지 않습니다.
숫자를 해상도로 반올림하는 가장 좋은 방법은 다음 방법으로 모든 해상도에서 작동 할 수 있습니다 (소수점 두 자리 또는 다른 단계의 경우 0.01).
>>> import numpy as np
>>> value = 13.949999999999999
>>> resolution = 0.01
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
13.95
>>> resolution = 0.5
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
14.0
numpy.round
정확성 / 정밀도 에서 비롯된 것 같습니다 . 따라서 해상도와 곱하기 전에 int로 정의해야합니다. 코드를 업데이트했습니다. 감사합니다!
numpy.float64
np.round의 결과 를로 변환 float
하거나 단순히 사용하는 것 round(value, 2)
입니다. 13.949999999999999 (= 1395/100.)와 3.950000000000001 (= 1395 * .01) 사이에 유효한 IEEE 754 번호가 없습니다. 왜 당신의 방법이 최고라고 생각합니까? 원래 값 13.949999999999999289 (= value = round (value, 2))는 13.95000000000000178 (np.float96으로 인쇄)보다 훨씬 정확합니다. numpy에 대한 추가 정보가 이제 내 대답에 추가 되어 실수로 다운 투표 할 수 있습니다. 원래 numpy에 관한 것이 아닙니다.
int
사용할 수 있음을 확인했습니다 float
. 추가 의견에 감사드립니다. (죄송하지만 난 당신을
내가 사용하는 방법은 문자열 슬라이싱 방법입니다. 비교적 빠르고 간단합니다.
먼저 float를 문자열로 변환하고 원하는 길이를 선택하십시오.
float = str(float)[:5]
위의 한 줄에서 값을 문자열로 변환 한 다음 문자열을 처음 네 자리 또는 문자 (포함)로만 유지했습니다.
희망이 도움이됩니다!