四舍五入为有效数字 [英] Rounding to significant figures in numpy
问题描述
我尝试搜索此内容,但找不到满意的答案.
I've tried searching this and can't find a satisfactory answer.
我想获取一个数字列表/数组,并将它们四舍五入为n个有效数字.我已经编写了一个函数来执行此操作,但是我想知道是否有标准方法可以执行此操作?我已经搜索了,但是找不到.示例:
I want to take a list/array of numbers and round them all to n significant figures. I have written a function to do this, but I was wondering if there is a standard method for this? I've searched but can't find it. Example:
In: [ 0.0, -1.2366e22, 1.2544444e-15, 0.001222 ], n=2
Out: [ 0.00, -1.24e22, 1.25e-15, 1.22e-3 ]
谢谢
推荐答案
首先提出批评:您所计算的有效数字错误.在您的示例中,您希望n = 3,而不是2.
First a criticism: you're counting the number of significant figures wrong. In your example you want n=3, not 2.
如果使用使该算法的二进制版本变得简单的函数,则可以通过让numpy库函数处理它们来解决大多数情况.另外,由于该算法从不调用log函数,因此它的运行速度也快得多.
It is possible to get around most of the edge cases by letting numpy library functions handle them if you use the function that makes the binary version of this algorithm simple: frexp. As a bonus, this algorithm will also run much faster because it never calls the log function.
#The following constant was computed in maxima 5.35.1 using 64 bigfloat digits of precision
__logBase10of2 = 3.010299956639811952137388947244930267681898814621085413104274611e-1
import numpy as np
def RoundToSigFigs_fp( x, sigfigs ):
"""
Rounds the value(s) in x to the number of significant figures in sigfigs.
Return value has the same type as x.
Restrictions:
sigfigs must be an integer type and store a positive value.
x must be a real value.
"""
if not ( type(sigfigs) is int or type(sigfigs) is long or
isinstance(sigfigs, np.integer) ):
raise TypeError( "RoundToSigFigs_fp: sigfigs must be an integer." )
if sigfigs <= 0:
raise ValueError( "RoundToSigFigs_fp: sigfigs must be positive." )
if not np.isreal( x ):
raise TypeError( "RoundToSigFigs_fp: x must be real." )
xsgn = np.sign(x)
absx = xsgn * x
mantissa, binaryExponent = np.frexp( absx )
decimalExponent = __logBase10of2 * binaryExponent
omag = np.floor(decimalExponent)
mantissa *= 10.0**(decimalExponent - omag)
if mantissa < 1.0:
mantissa *= 10.0
omag -= 1.0
return xsgn * np.around( mantissa, decimals=sigfigs - 1 ) * 10.0**omag
它可以正确处理您的所有情况,包括无限,nan,0.0和次正规数:
And it handles all of your cases correctly, including infinite, nan, 0.0, and a subnormal number:
>>> eglist = [ 0.0, -1.2366e22, 1.2544444e-15, 0.001222, 0.0,
... float("nan"), float("inf"), float.fromhex("0x4.23p-1028"),
... 0.5555, 1.5444, 1.72340, 1.256e-15, 10.555555 ]
>>> eglist
[0.0, -1.2366e+22, 1.2544444e-15, 0.001222, 0.0,
nan, inf, 1.438203867284623e-309,
0.5555, 1.5444, 1.7234, 1.256e-15, 10.555555]
>>> RoundToSigFigs(eglist, 3)
array([ 0.00000000e+000, -1.24000000e+022, 1.25000000e-015,
1.22000000e-003, 0.00000000e+000, nan,
inf, 1.44000000e-309, 5.56000000e-001,
1.54000000e+000, 1.72000000e+000, 1.26000000e-015,
1.06000000e+001])
>>> RoundToSigFigs(eglist, 1)
array([ 0.00000000e+000, -1.00000000e+022, 1.00000000e-015,
1.00000000e-003, 0.00000000e+000, nan,
inf, 1.00000000e-309, 6.00000000e-001,
2.00000000e+000, 2.00000000e+000, 1.00000000e-015,
1.00000000e+001])
2016/10/12我发现原始代码处理错误的一个极端情况.我在GitHub存储库中放置了完整版代码.
2016/10/12 I found an edge case that the original code handled wrong. I have placed a fuller version of the code in a GitHub repository.
2019/03/01替换为重新编码的版本.
2019/03/01 Replace with recoded version.
这篇关于四舍五入为有效数字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!