4

注意:这个问题是关于有效数字的。这不是关于“小数点后的数字”或类似问题的问题。

编辑:这个问题不是小数模块中有效数字的重复。这两个问题问的是完全不同的问题。我想知道为什么函数 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

4

2 回答 2

5

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

当您调用 时,由于从源代码转换为二进制浮点to_sigfigs(0.000001, 5),已经存在一些舍入误差。0.000001实际上是 9.99999999999999954748111825886258685613938723690807819366455078125E-7。将其四舍五入到 5 位有效数字给出decimal.Decimal("0.0000010000").

另一方面,1 可以用二进制浮点数精确表示,所以 1 也可以精确表示1.0。由于只需要 1 位就可以用十进制表示,因此上下文的精度不需要任何舍入,你会得到一个 1 位的十进制结果.

于 2015-12-10T21:24:39.920 回答
2

它是一个错误吗?我不知道,我认为文档不够紧密,无法做出这个决定。这当然是一个令人惊讶的结果。

可以使用更多逻辑来修复您自己的功能。

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)))
于 2015-12-10T22:15:44.783 回答