如何在 Python 中将数字四舍五入为有效数字

2024-12-26 08:43:00
admin
原创
158
摘要:问题描述:我需要将浮点数四舍五入以显示在 UI 中。例如,四舍五入为一个有效数字:1234 -> 1000 0.12 -> 0.1 0.012 -> 0.01 0.062 -> 0.06 6253 -> 6000 1999 -> 2000 有没有使用 Python...

问题描述:

我需要将浮点数四舍五入以显示在 UI 中。例如,四舍五入为一个有效数字:

1234 -> 1000

0.12 -> 0.1

0.012 -> 0.01

0.062 -> 0.06

6253 -> 6000

1999 -> 2000

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


解决方案 1:

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

>>> 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,您可能需要小心地将浮点数转换为整数。

解决方案 2:

字符串格式化中的 %g 将把浮点数四舍五入为若干有效数字。它有时会使用“e”科学计数法,因此将四舍五入后的字符串转换回浮点数,然后通过 %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'

解决方案 3:

f'{float(f"{i:.1g}"):g}'
# Or with Python <3.6,
'{:g}'.format(float('{:.1g}'.format(i)))

此解决方案:

  1. 准确回答了这个问题

  2. 不需要任何额外的包装

  3. 不需要任何用户定义的辅助函数或数学运算

对于任意数量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']

注意:使用此解决方案,无法根据输入动态调整有效数字的数量,因为没有标准方法来区分尾随零的数量不同的数字( )。如果需要这样做,则需要非标准函数,例如to-precision3.14 == 3.1400包中提供的函数。

解决方案 4:

如果您希望有除 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

解决方案 5:

为了直接回答这个问题,这是我使用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.07 而不是 0.08。正如“新手 C”所指出的,这是由于浮点运算既具有有限精度又具有以 2 为基数的表示法。实际上可以表示的最接近 0.075 的数字略小,因此四舍五入的结果可能与您天真地预期的不同。

还请注意,这适用于任何非十进制浮点运算的使用,例如 C 和 Java 都存在同样的问题。

为了更详细地显示,我们要求 Python 以“十六进制”格式格式化数字:

0.075.hex()

结果是:0x1.3333333333333p-4。这样做的原因是,正常的十进制表示通常涉及四舍五入,因此不是计算机实际“看到”的数字。如果您不习惯这种格式,可以参考Python 文档和C 标准。

为了说明这些数字是如何工作的,我们可以通过执行以下操作回到起点:

0x13333333333333 / 16**13 * 2**-4

应该打印出0.07516**13是因为小数点后有 13 位十六进制数字,并且2**-4是因为十六进制指数以 2 为底。

现在我们对浮点数的表示方式有了一些了解,我们可以使用该decimal模块来提供更高的精度,并向我们展示正在发生的事情:

from decimal import Decimal

Decimal(0x13333333333333) / 16**13 / 2**4

给予:0.07499999999999999722444243844并希望解释为什么round(0.075, 2)评估为0.07

解决方案 6:

我创建了to-precision包,它可以满足您的要求。它允许您为数字赋予更多或更少的有效数字。

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

在接受的答案中有一行

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

解决方案 7:

发布的答案是给出时最好的答案,但它有许多局限性,并且不能产生技术上正确的有效数字。

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.

解决方案 8:

要将整数四舍五入为 1 位有效数字,基本思想是将其转换为小数点前有 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)

解决方案 9:

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

解决方案 10:

sigfig包/库涵盖了这一点。安装后,您可以执行以下操作:

>>> from sigfig import round
>>> round(1234, 1)
1000
>>> round(0.12, 1)
0.1
>>> round(0.012, 1)
0.01
>>> round(0.062, 1)
0.06
>>> round(6253, 1)
6000
>>> round(1999, 1)
2000

解决方案 11:

我修改了 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)

解决方案 12:

如果您想在不涉及字符串的情况下进行舍入,我在上面的评论中找到了链接:

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

如果由于某种原因您正在处理微小的值,则不会引起错误。

解决方案 13:

我改编了其中一个答案。我喜欢这个:

def sigfiground(number:float, ndigits=3)->float:
    return float(f"{number:.{ndigits}g}")

当我仍然想要浮点数时我会使用它(我在其他地方进行格式化)。

解决方案 14:

我想不出有什么可以立即处理这个问题。但它对浮点数的处理相当好。

>>> round(1.2322, 2)
1.23

整数比较棘手。它们不是以十进制形式存储在内存中的,因此显着位置不是自然而然的事情。不过,一旦它们是字符串,实现起来就相当简单了。

或者对于整数:

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

如果您想创建一个处理任何数字的函数,我倾向于将它们都转换为字符串并寻找小数位来决定要做什么:

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)

解决方案 15:

有效数字的科学计数法已作为函数包含在 numpy 版本 1.21.0 中。截至 2024 年 8 月 18 日:

import numpy as np

# define the required number of significant figures
sig_fig = 2

# compensate for that the precision is always one magnitude
# higher than the number of significant figures:

num_to_sig_fig_str = np.format_float_scientific( 
    123.456789, precision = sig_fig - 1 
    )

num_to_sig_fig_str
> '1.2e+02'

# to convert back to a number using the same precision  
# as the number of significant figures, use float():

float(num_to_sig_fig_str)
> 120.0

文档:
https ://numpy.org/doc/stable/reference/generated/numpy.format_float_scientific.html

解决方案 16:

使用 python 2.6+新样式格式(因为 %-style 已被弃用):

>>> "{0}".format(float("{0:.1g}".format(1216)))
'1000.0'
>>> "{0}".format(float("{0:.1g}".format(0.00356)))
'0.004'

在 python 2.7+ 中,您可以省略前导0s。

解决方案 17:

这些答案中的大多数涉及数学、十进制和/或 numpy 导入或输出值作为字符串。这是一个使用基本 Python 的简单解决方案,它可以处理大数和小数并输出浮点数:

def sig_fig_round(number, digits=3):
    power = "{:e}".format(number).split('e')[1]
    return round(number, -(int(power) - digits))

解决方案 18:

我编写了一个名为sciform的 PyPi 包,它可以轻松执行这种舍入并支持其他科学格式选项。

from sciform import Formatter

sform = Formatter(
    round_mode="sig_fig",  # This is the default
    ndigits=1,
)

num_list = [
    1234,
    0.12,
    0.012,
    0.062,
    6253,
    1999,
]

for num in num_list:
    result = sform(num)
    print(f'{num} -> {result}')

# 1234 -> 1000
# 0.12 -> 0.1
# 0.012 -> 0.01
# 0.062 -> 0.06
# 6253 -> 6000
# 1999 -> 2000

sciform部分原因是 Python 内置的格式规范迷你语言并不总是提供精确的四舍五入到有效数字,同时也始终使用所需的定点行为。该g选项可以正确获得有效数字。如果您希望有效数字在小数点以下工作(即0.1变为0.102 位有效数字),则必须使用该#选项,但该#选项意味着不会删除尾随小数点,因此120->1.e+02为一位有效数字。

特别参阅Python 话语讨论中的这条评论。

num_list = [
    1234,
    0.12,
    0.012,
    0.062,
    6253,
    1999,
]

for num in num_list:
    print(f'{num} -> {num:#.1g}')

# 1234 -> 1e+03
# 0.12 -> 0.1
# 0.012 -> 0.01
# 0.062 -> 0.06
# 6253 -> 6.e+03
# 1999 -> 2.e+03

解决方案 19:

我也遇到过这种情况,但我需要控制舍入类型。因此,我编写了一个快速函数(见下面的代码),它可以考虑值、舍入类型和所需的有效数字。

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

解决方案 20:

如果数字大于 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)

希望有帮助。

解决方案 21:

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

解决方案 22:

这将返回一个字符串,以便正确显示没有小数部分的结果和 E 符号中出现的小值:

def sigfig(x, num_sigfig):
    num_decplace = num_sigfig - int(math.floor(math.log10(abs(x)))) - 1
    return '%.*f' % (num_decplace, round(x, num_decplace))

解决方案 23:

使用标准十进制库的简单变体

from decimal import Decimal

def to_significant_figures(v: float, n_figures: int) -> str:
    d = Decimal(v)
    d = d.quantize(Decimal((0, (), d.adjusted() - n_figures + 1)))
    return str(d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize())

测试

>>> to_significant_figures(1.234567, 3)
'1.23'
>>> to_significant_figures(1234567, 3)
'1230000'
>>> to_significant_figures(1.23, 7)
'1.23'
>>> to_significant_figures(123, 7)
'123'

解决方案 24:

此函数接受正数和负数,并进行正确的有效数字舍入。

from math import floor

def significant_arithmetic_rounding(n, d):
    '''
    This function takes a floating point number and the no. of significant digit d, perform significant digits
    arithmetic rounding and returns the floating point number after rounding
    '''
    if n == 0:
        return 0
    else:
        # Checking whether the no. is negative or positive. If it is negative we will take the absolute value of it and proceed
        neg_flag = 0
        if n < 0:
            neg_flag = 1
            n = abs(n)
        
        n1 = n   
        # Counting the no. of digits to the left of the decimal point in the no.
        ld = 0
        while(n1 >= 1):
            n1 /= 10
            ld += 1
        
        n1 = n
        # Counting the no. of zeros to the right of the decimal point and before the first significant digit in the no.
        z = 0
        if ld == 0:
            while(n1 <= 0.1):
                n1 *= 10
                z += 1
        
        n1 = n
        # No. of digits to be considered after decimal for rounding
        rd = (d - ld) + z
        n1 *= 10**rd
    
        # Increase by 0.5 and take the floor value for rounding
        n1 = floor(n1+0.5)
        # Placing the decimal point at proper position
        n1 /= 10 ** rd
        # If the original number is negative then make it negative
        if neg_flag == 1:
            n1 = 0 - n1

        return n1

测试:

>>> significant_arithmetic_rounding(1234, 3)
1230.0
>>> significant_arithmetic_rounding(123.4, 3)
123.0
>>> significant_arithmetic_rounding(0.0012345, 3)
0.00123
>>> significant_arithmetic_rounding(-0.12345, 3)
-0.123
>>> significant_arithmetic_rounding(-30.15345, 3)
-30.2

解决方案 25:

更容易知道答案是否适合您的需求,只要它包含示例即可。以下内容基于以前的解决方案,但提供了更通用的函数,可以四舍五入为 1、2、3、4 或任意数量的有效数字。

import math

# Given x as float or decimal, returns as string a number rounded to "sig" significant digts
# Return as string in order to control significant digits, could be a float or decimal 
def round_sig(x, sig=2):
  r = round(x, sig-int(math.floor(math.log10(abs(x))))-1)
  floatsig = "%." + str(sig) + "g"
  return "%d"%r if abs(r) >= 10**(sig-1) else '%s'%float(floatsig % r) 

>>> a = [1234, 123.4, 12.34, 1.234, 0.1234, 0.01234, 0.25, 1999, -3.14, -48.01, 0.75]
>>> [print(i, "->", round_sig(i,1), round_sig(i), round_sig(i,3), round_sig(i,4)) for i in a]

1234 -> 1000 1200 1230 1234
123.4 -> 100 120 123 123.4
12.34 -> 10 12 12.3 12.34
1.234 -> 1 1.2 1.23 1.234
0.1234 -> 0.1 0.12 0.123 0.1234
0.01234 -> 0.01 0.012 0.0123 0.01234
0.25 -> 0.2 0.25 0.25 0.25
1999 -> 2000 2000 2000 1999
-3.14 -> -3 -3.1 -3.14 -3.14
-48.01 -> -50 -48 -48.0 -48.01
0.75 -> 0.8 0.75 0.75 0.75

解决方案 26:

在极少数情况下,有效数字取决于评估过程,例如错误。我编写了一些代码,根据错误返回一个数字(或一些所需的数字),并以字符串形式返回(不会消除右侧有效零)

import numpy as np

def Sig_Digit(x, *N,):
    if abs(x) < 1.0e-15:
        return(1)
    N = 1 if N ==() else N[0]
    k = int(round(abs(N)-1))-int(np.floor(np.log10(abs(x))))
    return(k);

def Sig_Format(x, *Error,):
    if abs(x) < 1.0e-15:
        return('{}')
    Error = 1 if Error ==() else abs(Error[0])
    k = int(np.floor(np.log10(abs(x))))
    z = x/10**k
    k = -Sig_Digit(Error, 1)
    m = 10**k
    y = round(x*m)/m
    if k < 0:
        k = abs(k)
        if z >= 9.5:
            FMT = '{:'+'{}'.format(1+k)+'.'+'{}'.format(k-1)+'f}'
        else:
            FMT = '{:'+'{}'.format(2+k)+'.'+'{}'.format(k)+'f}'
    elif k == 0:
        if z >= 9.5:
            FMT = '{:'+'{}'.format(1+k)+'.0e}'
        else:
            FMT = '{:'+'{}'.format(2+k)+'.0f}'
    else:
        FMT = '{:'+'{}'.format(2+k)+'.'+'{}'.format(k)+'e}'
    return(FMT)

def Sci_Format(x, *N):
    if abs(x) < 1.0e-15:
        return('{}')
    N = 1 if N ==() else N[0]
    N = int(round(abs(N)-1))
    y = abs(x)
    k = int(np.floor(np.log10(y)))
    z = x/10**k
    k = k-N
    m = 10**k
    y = round(x/m)*m
    if k < 0:
        k = abs(k)
        if z >= 9.5:
            FMT = '{:'+'{}'.format(1+k)+'.'+'{}'.format(k-1)+'f}'
        else:
            FMT = '{:'+'{}'.format(2+k)+'.'+'{}'.format(k)+'f}'
    elif k == 0:
        if z >= 9.5:
            FMT = '{:'+'{}'.format(1+k)+'.0e}'
        else:
            FMT = '{:'+'{}'.format(2+k)+'.0f}'
    else:
        FMT = '{:'+'{}'.format(2+N)+'.'+'{}'.format(N)+'e}'
    return(FMT)

def Significant(x, *Error):
    N = 0 if Error ==() else Sig_Digit(abs(Error[0]), 1)
    m = 10**N
    y = round(x*m)/m
    return(y)

def Scientific(x, *N):
    m = 10**Sig_Digit(x, *N)
    y = round(x*m)/m
    return(y)

def Scientific_Str(x, *N,): 
    FMT = Sci_Format(x, *N)
    return(FMT.format(x))

def Significant_Str(x, *Error,):    
    FMT = Sig_Format(x, *Error)
    return(FMT.format(x))

测试代码:

X = [19.03345607, 12.075, 360.108321344, 4325.007605343]
Error = [1.245, 0.1245, 0.0563, 0.01245, 0.001563, 0.0004603]
for x in X:
    for error in Error:
        print(x,'+/-',error, end='       ==> ')
        print(' (',Significant_Str(x, error), '+/-', Scientific_Str(error),')')

  

打印出:

19.03345607 +/- 1.245       ==>  ( 19 +/-  1 )

19.03345607 +/- 0.1245      ==>  ( 19.0 +/- 0.1 )

19.03345607 +/- 0.0563      ==>  ( 19.03 +/- 0.06 )

19.03345607 +/- 0.01245     ==>  ( 19.03 +/- 0.01 )

19.03345607 +/- 0.001563    ==>  ( 19.033 +/- 0.002 )

19.03345607 +/- 0.0004603       ==>  ( 19.0335 +/- 0.0005 )

12.075 +/- 1.245    ==>  ( 12 +/-  1 )

12.075 +/- 0.1245       ==>  ( 12.1 +/- 0.1 )

12.075 +/- 0.0563       ==>  ( 12.07 +/- 0.06 )

12.075 +/- 0.01245      ==>  ( 12.07 +/- 0.01 )

12.075 +/- 0.001563     ==>  ( 12.075 +/- 0.002 )

12.075 +/- 0.0004603    ==>  ( 12.0750 +/- 0.0005 )

360.108321344 +/- 1.245     ==>  ( 360 +/-  1 )

360.108321344 +/- 0.1245    ==>  ( 360.1 +/- 0.1 )

360.108321344 +/- 0.0563    ==>  ( 360.11 +/- 0.06 )

360.108321344 +/- 0.01245       ==>  ( 360.11 +/- 0.01 )

360.108321344 +/- 0.001563      ==>  ( 360.108 +/- 0.002 )

360.108321344 +/- 0.0004603     ==>  ( 360.1083 +/- 0.0005 )

4325.007605343 +/- 1.245    ==>  ( 4325 +/-  1 )

4325.007605343 +/- 0.1245       ==>  ( 4325.0 +/- 0.1 )

4325.007605343 +/- 0.0563       ==>  ( 4325.01 +/- 0.06 )

4325.007605343 +/- 0.01245      ==>  ( 4325.01 +/- 0.01 )

4325.007605343 +/- 0.001563     ==>  ( 4325.008 +/- 0.002 )

4325.007605343 +/- 0.0004603    ==>  ( 4325.0076 +/- 0.0005 )

解决方案 27:

内置round四舍五入x到选定的小数位。如果我们想四舍五入到有效数字,我们需要知道第一个有效数字的位置。log10四舍五入abs(x)将给出第一个有效数字的位置:math.floor(math.log10(abs(x)))

因此,四舍五入到 1 位有效数字的函数x如下:

import math

def round_1sig(x):
    if x == 0: return x
    return round(x, -math.floor(math.log10(abs(x))))

更一般地,四舍五入xnsig有效数字的函数如下:

def round_nsig(x, nsig):
    if x == 0: return x
    return round(x, -math.floor(math.log10(abs(x))) + nsig - 1)

解决方案 28:

虽然上面的很多都差不多,但这更符合我的审美

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() 也会返回小数(例如,对于 importantFigures=2,我们可能期望返回 -460,但实际上我们得到的是 -460.0)。我们可以添加此步骤来纠正此问题:

if roundingFactor<=0:
    rounded=rounded.astype(int)

不幸的是,这最后一步不适用于数字数组——如果您需要的话,我会把它留给亲爱的读者去弄清楚。

解决方案 29:

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
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1579  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1355  
  信创产品在政府采购中的占比分析随着信息技术的飞速发展以及国家对信息安全重视程度的不断提高,信创产业应运而生并迅速崛起。信创,即信息技术应用创新,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,保障国家信息安全。政府采购作为推动信创产业发展的重要力量,其对信创产品的采购占比情况备受关注。这不仅关系到信创产业的发展前...
信创和国产化的区别   8  
  信创,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,摆脱对国外技术的依赖。近年来,国货国用信创发展势头迅猛,在诸多领域取得了显著成果。这一发展趋势对科技创新产生了深远的推动作用,不仅提升了我国在信息技术领域的自主创新能力,还为经济社会的数字化转型提供了坚实支撑。信创推动核心技术突破信创产业的发展促使企业和科研...
信创工作   9  
  信创技术,即信息技术应用创新产业,旨在实现信息技术领域的自主可控与安全可靠。近年来,信创技术发展迅猛,对中小企业产生了深远的影响,带来了诸多不可忽视的价值。在数字化转型的浪潮中,中小企业面临着激烈的市场竞争和复杂多变的环境,信创技术的出现为它们提供了新的发展机遇和支撑。信创技术对中小企业的影响技术架构变革信创技术促使中...
信创国产化   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用