UI에 표시하려면 플로트를 반올림해야합니다. 예를 들어, 한 가지 중요한 수치입니다.
1234-> 1000
0.12-> 0.1
0.012-> 0.01
0.062-> 0.06
6253-> 6000
1999-> 2000
파이썬 라이브러리를 사용 하여이 작업을 수행하는 좋은 방법이 있습니까? 아니면 직접 작성해야합니까?
UI에 표시하려면 플로트를 반올림해야합니다. 예를 들어, 한 가지 중요한 수치입니다.
1234-> 1000
0.12-> 0.1
0.012-> 0.01
0.062-> 0.06
6253-> 6000
1999-> 2000
파이썬 라이브러리를 사용 하여이 작업을 수행하는 좋은 방법이 있습니까? 아니면 직접 작성해야합니까?
답변:
음수를 사용하여 정수를 반올림 할 수 있습니다.
>>> round(1234, -3)
1000.0
따라서 가장 중요한 숫자 만 필요한 경우 :
>>> from math import log10, floor
>>> def round_to_1(x):
... return round(x, -int(floor(log10(abs(x)))))
...
>>> round_to_1(0.0232)
0.02
>>> round_to_1(1234243)
1000000.0
>>> round_to_1(13)
10.0
>>> round_to_1(4)
4.0
>>> round_to_1(19)
20.0
float가 1보다 큰 경우 float를 정수로 바꾸어야 할 것입니다.
log10
반올림 방법을 결정하는 유일한 방법은 사용 입니다.
log10(abs(x))
. 그렇지 않으면 음수가 실패합니다 ( x == 0
물론 별도 취급 )
round_to_n = lambda x, n: x if x == 0 else round(x, -int(math.floor(math.log10(abs(x)))) + (n - 1))
@RoyHyunjinHan 및 @TobiasKienzler 로부터 보호 x==0
하고 x<0
감사합니다. math.inf와 같은 undefined 나 None과 같은 쓰레기로부터 보호되지 않습니다
문자열 형식의 % g는 부동 소수점을 몇 개의 유효 숫자로 반올림합니다. 때로는 'e'과학 표기법을 사용하므로 둥근 문자열을 다시 float로 변환 한 다음 % s 문자열 형식을 통해 변환하십시오.
>>> '%s' % float('%.1g' % 1234)
'1000'
>>> '%s' % float('%.1g' % 0.12)
'0.1'
>>> '%s' % float('%.1g' % 0.012)
'0.01'
>>> '%s' % float('%.1g' % 0.062)
'0.06'
>>> '%s' % float('%.1g' % 6253)
'6000.0'
>>> '%s' % float('%.1g' % 1999)
'2000.0'
0.075
로 0.08
. 0.07
대신 반환 합니다.
round_sig = lambda f,p: float(('%.' + str(p) + 'e') % f)
유효 자릿수를 조정할 수 있습니다!
유효 숫자가 1이 아닌 다른 값을 가지려면 (그렇지 않으면 Evgeny와 동일) :
>>> from math import log10, floor
>>> def round_sig(x, sig=2):
... return round(x, sig-int(floor(log10(abs(x))))-1)
...
>>> round_sig(0.0232)
0.023
>>> round_sig(0.0232, 1)
0.02
>>> round_sig(1234243, 3)
1230000.0
0.075
로 0.08
. 0.07
대신 반환 합니다.
round
. docs.python.org/2/tutorial/floatingpoint.html#tut-fp-issues
f'{float(f"{i:.1g}"):g}'
# Or with Python <3.6,
'{:g}'.format(float('{:.1g}'.format(i)))
이 솔루션은 다음과 같은 이유로 다른 솔루션과 다릅니다.
임의 n
의 유효 숫자에 대해서는 다음을 사용할 수 있습니다.
print('{:g}'.format(float('{:.{p}g}'.format(i, p=n))))
테스트:
a = [1234, 0.12, 0.012, 0.062, 6253, 1999, -3.14, 0., -48.01, 0.75]
b = ['{:g}'.format(float('{:.1g}'.format(i))) for i in a]
# b == ['1000', '0.1', '0.01', '0.06', '6000', '2000', '-3', '0', '-50', '0.8']
참고 :이 솔루션을 사용하면 후행 0의 숫자가 다른 숫자를 구별하는 표준 방법이 없으므로 입력에서 유효 숫자의 숫자를 동적으로 조정할 수 없습니다 3.14 == 3.1400
. 그렇게 하려면 정밀 패키지에 제공된 것과 같은 비표준 기능 이 필요합니다.
:g
정수를 유지 하는 포맷터 의 이중 사용입니다 .
2000.0
은 5 자리 유효 숫자를 나타내 므로 {:g}
다시 통과 해야합니다.) 일반적으로, 마지막 0보다 큰 일부 기법을 사용하지 않는 한, 후행 0을 갖는 정수는 중요한 수치와 관련하여 모호합니다.
원하는 것을 수행하는 정밀 패키지 를 만들었습니다 . 그것은 당신이 당신의 숫자에 다소 중요한 수치를 줄 수 있습니다.
또한 지정된 유효 숫자로 표준, 과학 및 공학 표기법을 출력합니다.
허용 된 답변에는 선이 있습니다.
>>> round_to_1(1234243)
1000000.0
실제로 8 시그마 무화과를 지정합니다. 숫자 1234243의 경우 내 라이브러리에는 하나의 중요한 그림 만 표시됩니다.
>>> from to_precision import to_precision
>>> to_precision(1234243, 1, 'std')
'1000000'
>>> to_precision(1234243, 1, 'sci')
'1e6'
>>> to_precision(1234243, 1, 'eng')
'1e6'
또한 마지막 유효 숫자를 반올림하고 표기법이 지정되지 않은 경우 사용할 표기법을 자동으로 선택할 수 있습니다.
>>> to_precision(599, 2)
'600'
>>> to_precision(1164, 2)
'1.2e3'
lambda x: to_precision(x, 2)
정수를 1의 유효 숫자로 반올림하려면 기본 아이디어는 소수점 앞의 1 자리가있는 부동 소수점으로 변환하고 반올림 한 다음 원래 정수 크기로 다시 변환하는 것입니다.
이를 위해서는 정수보다 10의 가장 큰 거듭 제곱을 알아야합니다. 이를 위해 log 10 기능의 플로어를 사용할 수 있습니다.
from math import log10, floor def round_int(i,places): if i == 0: return 0 isign = i/abs(i) i = abs(i) if i < 1: return 0 max10exp = floor(log10(i)) if max10exp+1 < places: return i sig10pow = 10**(max10exp-places+1) floated = i*1.0/sig10pow defloated = round(floated)*sig10pow return int(defloated*isign)
질문에 직접 대답하기 위해 R 함수의 명명을 사용하는 내 버전은 다음과 같습니다.
import math
def signif(x, digits=6):
if x == 0 or not math.isfinite(x):
return x
digits -= math.ceil(math.log10(abs(x)))
return round(x, digits)
이 답변을 게시 한 주된 이유는 "0.075"가 0.08이 아니라 0.07로 반올림된다고 불평하는 의견입니다. 이것은 "초보자 C"가 지적한 바와 같이 유한 정밀도와 밑수 -2 표현 을 모두 갖는 부동 소수점 산술의 조합 때문입니다. . 실제로 표현할 수있는 0.075에 가장 가까운 숫자는 약간 작으므로 반올림은 예상과 다르게 나타납니다.
또한 이것은 10 진수가 아닌 부동 소수점 산술의 사용에 적용됩니다 (예 : C와 Java 모두 동일한 문제가 있음).
더 자세하게 보여주기 위해, 파이썬에게 숫자를 "16 진수"형식으로 포맷하도록 요청합니다 :
0.075.hex()
그것은 우리에게 : 0x1.3333333333333p-4
. 이 작업을 수행하는 이유는 일반적인 십진수 표현은 반올림을 포함하기 때문에 컴퓨터가 실제로 숫자를 "인식"하는 방식이 아니기 때문입니다. 이 형식에 익숙하지 않은 경우 몇 가지 유용한 참조는 Python 문서 와 C 표준입니다. 입니다.
이 숫자가 어떻게 작동하는지 보여주기 위해 다음을 수행하여 시작점으로 돌아갈 수 있습니다.
0x13333333333333 / 16**13 * 2**-4
인쇄해야합니다 0.075
. 16**13
소수점 뒤에 13 개의 16 진수가 있기 때문입니다.2**-4
진 지수가 밑이 2이기 때문입니다.
이제 float가 어떻게 표현되는지에 대한 아이디어를 얻었습니다. decimal
모듈을 사용하여 좀 더 정밀한 결과를 보여줍니다.
from decimal import Decimal
Decimal(0x13333333333333) / 16**13 / 2**4
제공 : 0.07499999999999999722444243844
그리고 왜 round(0.075, 2)
평가하는 이유를 희망적으로 설명0.07
0.074999999999999999
, 당신이이 경우에 얻을 기대?
def round_to_n(x, n):
if not x: return 0
power = -int(math.floor(math.log10(abs(x)))) + (n - 1)
factor = (10 ** power)
return round(x * factor) / factor
round_to_n(0.075, 1) # 0.08
round_to_n(0, 1) # 0
round_to_n(-1e15 - 1, 16) # 1000000000000001.0
희망적으로 위의 모든 답변을 최대한 활용하십시오 (한 줄에 람다로 넣을 수 있음). 아직 탐색하지 않은 경우이 답변을 자유롭게 편집하십시오.
round_to_n(1e15 + 1, 11) # 999999999999999.9
음수와 작은 숫자 (0 포함)를 처리하기 위해 indgar의 솔루션을 수정했습니다.
from math import log10, floor
def round_sig(x, sig=6, small_value=1.0e-9):
return round(x, sig - int(floor(log10(max(abs(x), abs(small_value))))) - 1)
x == 0
습니까? 원 라이너를 좋아한다면 그냥 return 0 if x==0 else round(...)
.
0.970 == 0.97
. f'{round_sig(0.9701, sig=3):0.3f}'
제로 인쇄를 원하는 경우 와 같은 다른 인쇄 솔루션을 사용할 수 있다고 생각합니다 .
문자열을 사용하지 않고 반올림하려면 위의 주석에 묻힌 링크를 찾으십시오.
http://code.activestate.com/lists/python-tutor/70739/
나를 최고로 때린다. 그런 다음 문자열 형식 설명 자로 인쇄하면 합리적인 결과가 나오며 다른 계산 목적으로 숫자 표현을 사용할 수 있습니다.
링크의 코드는 def, doc 및 return의 세 가지 라이너입니다. 버그가 있습니다. 폭발 로그를 확인해야합니다. 쉽습니다. 입력을와 비교하십시오 sys.float_info.min
. 완벽한 솔루션은 다음과 같습니다.
import sys,math
def tidy(x, n):
"""Return 'x' rounded to 'n' significant digits."""
y=abs(x)
if y <= sys.float_info.min: return 0.0
return round( x, int( n-math.ceil(math.log10(y)) ) )
스칼라 숫자 값에 대해 작동하며 어떤 float
이유로 응답을 이동 해야하는 경우 n은 a가 될 수 있습니다 . 실제로 한도를 다음으로 푸시 할 수 있습니다.
sys.float_info.min*sys.float_info.epsilon
어떤 이유로 든 miniscule 값으로 작업하는 경우 오류를 유발하지 않습니다.
나는 이것을 즉시 처리 할 수있는 것을 생각할 수 없다. 그러나 부동 소수점 숫자에 대해서는 상당히 잘 처리됩니다.
>>> round(1.2322, 2)
1.23
정수는 까다 롭습니다. 메모리에 기본 10으로 저장되지 않으므로 중요한 장소는 자연스럽지 않습니다. 일단 문자열이면 구현하는 것이 매우 간단합니다.
또는 정수의 경우 :
>>> def intround(n, sigfigs):
... n = str(n)
... return n[:sigfigs] + ('0' * (len(n)-(sigfigs)))
>>> intround(1234, 1)
'1000'
>>> intround(1234, 2)
임의의 숫자를 처리하는 함수를 만들려면 선호하는 함수를 모두 문자열로 변환하고 소수점 이하 자릿수를 찾아서 수행 할 작업을 결정하는 것이 좋습니다.
>>> def roundall1(n, sigfigs):
... n = str(n)
... try:
... sigfigs = n.index('.')
... except ValueError:
... pass
... return intround(n, sigfigs)
다른 옵션은 유형을 확인하는 것입니다. 이것은 훨씬 유연하지 않으며 아마도 Decimal
객체 와 같은 다른 숫자와 잘 어울리지 않을 것입니다 .
>>> def roundall2(n, sigfigs):
... if type(n) is int: return intround(n, sigfigs)
... else: return round(n, sigfigs)
게시 된 답변은 제공 될 때 가장 유용했지만 많은 제한 사항이 있으며 기술적으로 올바른 수치를 나타내지 않습니다.
numpy.format_float_positional 은 원하는 동작을 직접 지원합니다. 다음 단편은 x
과학적 표기법이 억제 된 상태 에서 부동 소수점 을 유효 숫자 4 자리로 반환합니다 .
import numpy as np
x=12345.6
np.format_float_positional(x, precision=4, unique=False, fractional=False, trim='k')
> 12340.
print(*[''.join([np.format_float_positional(.01*a*n,precision=2,unique=False,fractional=False,trim='k',pad_right=5) for a in [.99, .999, 1.001]]) for n in [8,9,10,11,12,19,20,21]],sep='\n')
. Dragon4 자체는 확인하지 않았습니다.
나는 이것도 만났지만 반올림 유형을 제어해야했습니다. 따라서 값, 반올림 유형 및 원하는 유효 숫자를 고려할 수있는 빠른 기능 (아래 코드 참조)을 작성했습니다.
import decimal
from math import log10, floor
def myrounding(value , roundstyle='ROUND_HALF_UP',sig = 3):
roundstyles = [ 'ROUND_05UP','ROUND_DOWN','ROUND_HALF_DOWN','ROUND_HALF_UP','ROUND_CEILING','ROUND_FLOOR','ROUND_HALF_EVEN','ROUND_UP']
power = -1 * floor(log10(abs(value)))
value = '{0:f}'.format(value) #format value to string to prevent float conversion issues
divided = Decimal(value) * (Decimal('10.0')**power)
roundto = Decimal('10.0')**(-sig+1)
if roundstyle not in roundstyles:
print('roundstyle must be in list:', roundstyles) ## Could thrown an exception here if you want.
return_val = decimal.Decimal(divided).quantize(roundto,rounding=roundstyle)*(decimal.Decimal(10.0)**-power)
nozero = ('{0:f}'.format(return_val)).rstrip('0').rstrip('.') # strips out trailing 0 and .
return decimal.Decimal(nozero)
for x in list(map(float, '-1.234 1.2345 0.03 -90.25 90.34543 9123.3 111'.split())):
print (x, 'rounded UP: ',myrounding(x,'ROUND_UP',3))
print (x, 'rounded normal: ',myrounding(x,sig=3))
python 2.6+ 새로운 스타일 형식 사용 (% 스타일은 더 이상 사용되지 않음) :
>>> "{0}".format(float("{0:.1g}".format(1216)))
'1000.0'
>>> "{0}".format(float("{0:.1g}".format(0.00356)))
'0.004'
python 2.7 이상에서는 주요 0
s를 생략 할 수 있습니다 .
이 함수는 숫자가 10 ** (-decimal_positions)보다 큰 경우 일반 라운드를 수행하고, 그렇지 않으면 의미있는 소수 자릿수에 도달 할 때까지 더 많은 소수를 추가합니다.
def smart_round(x, decimal_positions):
dp = - int(math.log10(abs(x))) if x != 0.0 else int(0)
return round(float(x), decimal_positions + dp if dp > 0 else decimal_positions)
도움이 되길 바랍니다.
https://stackoverflow.com/users/1391441/gabriel 는 rnd (.075, 1)에 대한 우려 사항을 다음과 같이 해결합니까? 주의 사항 : 값을 부동 소수점으로 반환
def round_to_n(x, n):
fmt = '{:1.' + str(n) + 'e}' # gives 1.n figures
p = fmt.format(x).split('e') # get mantissa and exponent
# round "extra" figure off mantissa
p[0] = str(round(float(p[0]) * 10**(n-1)) / 10**(n-1))
return float(p[0] + 'e' + p[1]) # convert str to float
>>> round_to_n(750, 2)
750.0
>>> round_to_n(750, 1)
800.0
>>> round_to_n(.0750, 2)
0.075
>>> round_to_n(.0750, 1)
0.08
>>> math.pi
3.141592653589793
>>> round_to_n(math.pi, 7)
3.141593
왜 다른 질문을 추가하지 않습니까?
위의 많은 것들이 비교 가능하지만 이것은 내 미학에 조금 더 잘 맞습니다.
import numpy as np
number=-456.789
significantFigures=4
roundingFactor=significantFigures - int(np.floor(np.log10(np.abs(number)))) - 1
rounded=np.round(number, roundingFactor)
string=rounded.astype(str)
print(string)
이것은 개별 숫자와 numpy 배열에서 작동하며 음수에서는 잘 작동해야합니다.
추가 할 수있는 한 가지 추가 단계가 있습니다. np.round ()는 반올림이 정수인 경우에도 10 진수를 반환합니다 (즉, 상당한 숫자 = 2 인 경우 -460을 반환하지만 대신 -460.0을 얻을 수 있음). 이를 정정하기 위해이 단계를 추가 할 수 있습니다.
if roundingFactor<=0:
rounded=rounded.astype(int)
불행히도,이 마지막 단계는 일련의 숫자로 작동하지 않습니다. 필요한 경우 알아 내기 위해 독자에게 남겨 두겠습니다.
import math
def sig_dig(x, n_sig_dig):
num_of_digits = len(str(x).replace(".", ""))
if n_sig_dig >= num_of_digits:
return x
n = math.floor(math.log10(x) + 1 - n_sig_dig)
result = round(10 ** -n * x) * 10 ** n
return float(str(result)[: n_sig_dig + 1])
>>> sig_dig(1234243, 3)
>>> sig_dig(243.3576, 5)
1230.0
243.36