四舍五入为有效数字 [英] Rounding to significant figures in numpy

查看:207
本文介绍了四舍五入为有效数字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试搜索此内容,但找不到满意的答案.

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆