如何在Python中将数字舍入为有意义的数字

我需要围绕一个浮点数显示在用户界面。 例如,一个有意义的数字:

1234 – > 1000

0.12 – > 0.1

0.012 – > 0.01

0.062 – > 0.06

6253 – > 6000

1999年 – > 2000年

有没有一种很好的方式来使用Python库来做到这一点,还是我必须自己写?

您可以使用负数来整数整数:

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

如果大于1,你可能不得不把浮动转化为整数。

string格式中的%g将格式化浮点数为有效数字的浮点数。 它有时会使用'e'科学记数法,所以把四舍五入的string转换回一个浮点数,然后通过%s的string格式。

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

如果你想有不是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 

要将整数舍入为1有效数字,基本思想是将其转换为一个浮点数,然后将其转换回原来的整数大小。

要做到这一点,我们需要知道10的最大功率小于整数。 为此,我们可以使用log 10函数的floor。

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

希望能够把上面的所有答案都拿出来(减去能够把它作为一行的lambda;))。 还没有探索,请随时编辑这个答案:

 round_to_n(1e15 + 1, 11) # 999999999999999.9 

我修改了indgar的解决scheme来处理负数和小数字(包括零)。

 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) 

我想不出任何能够处理这个问题的东西。 但是,对于浮点数来说,它处理得相当好。

 >>> round(1.2322, 2) 1.23 

整数更棘手。 它们不是以10为基数存储的,所以重要的地方不是一件自然的事情。 一旦他们是一个string,它是相当微不足道的。

或整数:

 >>> def intround(n, sigfigs): ... n = str(n) ... return n[:sigfigs] + ('0' * (len(n)-(sigfigs))) >>> intround(1234, 1) '1000' >>> intround(1234, 2) 

如果你想创build一个处理任何数字的函数,我的首选是将它们都转换为string,并寻找一个小数位来决定做什么:

 >>> def roundall1(n, sigfigs): ... n = str(n) ... try: ... sigfigs = n.index('.') ... except ValueError: ... pass ... return intround(n, sigfigs) 

另一种select是检查types。 这将不太灵活,并且可能无法与其他数字(如“ Decimal对象:

 >>> def roundall2(n, sigfigs): ... if type(n) is int: return intround(n, sigfigs) ... else: return round(n, sigfigs) 

我已经在github.com/BebeSparkelSparkel/to-precision创build了精确的包 ,这是做你想做的。 我允许你给你的数字或多或less有意义的数字。

它还输出标准,科学和工程符号与指定数量的有效数字。

在接受的答案是有线

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

它也将围绕最后一个有效数字,并且可以自动select使用什么符号如果没有指定符号:

 >>> to_precision(599, 2) '600' >>> to_precision(1164, 2) '1.2e3' 

我碰到这个,但我需要控制舍入types。 因此,我写了一个快速函数(见下面的代码),可以将值,舍入types和所需的有效数字考虑在内。

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