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