为什么python十进制库不为某些输入返回指定数量的有效数字



NB:这个问题是关于有效数字的。这不是关于"小数点后的数字"之类的问题。

编辑:这个问题是而不是小数模块中有效数字的重复。这两个问题所问的问题完全不同。我想知道为什么about函数没有返回特定输入所需的值。小数模块中的有效数字的答案都没有解决这个问题。


以下函数应该返回具有指定有效位数的浮点值的字符串表示:

import decimal
def to_sigfigs(value, sigfigs):
    return str(decimal.Context(prec=sigfigs).create_decimal(value))

乍一看,它似乎起作用:

print to_sigfigs(0.000003141592653589793, 5)
# 0.0000031416
print to_sigfigs(0.000001, 5)
# 0.0000010000
print to_sigfigs(3.141592653589793, 5)
# 3.1416

但是

print to_sigfigs(1.0, 5)
# 1

最后一个表达式(IOW,1.0的5个有意义的数字表示)所需的输出是字符串"1.0000"。实际输出为字符串"1"。

我是误解了什么,还是这是decimal中的一个错误?

上下文的精度是最大精度;如果一个操作生成的Decimal的位数少于上下文的精度,则不会将其填充到上下文的精度。

当您调用to_sigfigs(0.000001, 5)时,由于源代码到二进制浮点的转换,0.000001已经有一些舍入错误。实际上是9.99999999999547448111825886258685613938723690807819366455078125E-7。四舍五入到5个有效数字得到decimal.Decimal("0.0000010000")

另一方面,1在二进制浮点中正好可以表示,所以1.0正好是1。由于只需要1位数字就可以用十进制表示,上下文的精度不需要任何舍入,因此可以得到1位十进制结果。

这是一个bug吗?我不知道,我认为文件不够紧凑,无法做出这样的决定。这当然是一个令人惊讶的结果。

可以用更多的逻辑来修复您自己的函数。

def to_sigfigs(value, sigfigs):
    sign, digits, exponent = decimal.Context(prec=sigfigs).create_decimal(value).as_tuple()
    if len(digits) < sigfigs:
        missing = sigfigs - len(digits)
        digits = digits + (0,) * missing
        exponent -= missing
    return str(decimal.Decimal((sign, digits, exponent)))

最新更新