为什么 python 十进制库 return 某些输入的指定有效数字位数
Why doesn't python decimal library return the specified number of signficant figures for some inputs
注意:这个问题是关于significant figures的。 不是关于"digits after the decimal point"或类似问题的问题。
编辑:这个问题不是 Significant figures in the decimal module. The two questions are asking about entirely different problems. I want to know why the function about does not return the desired value for a specific input. None of the answers to Significant figures in the decimal module 解决这个问题的副本。
以下函数应该 return 具有指定有效数字位数的浮点数的字符串表示形式:
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.99999999999999954748111825886258685613938723690807819366455078125E-7。四舍五入到 5 位有效数字得到 decimal.Decimal("0.0000010000")
.
另一方面,1 可以用二进制浮点数表示,所以 1.0
正好是 1。由于只需要 1 个数字来表示十进制,上下文的精度不需要任何舍入, 你会得到一个 1 位数的十进制结果。
这是一个错误吗?我不知道,我认为文档不够严密,无法做出该决定。这当然是一个令人惊讶的结果。
可以用更多的逻辑来修复你自己的函数。
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)))
注意:这个问题是关于significant figures的。 不是关于"digits after the decimal point"或类似问题的问题。
编辑:这个问题不是 Significant figures in the decimal module. The two questions are asking about entirely different problems. I want to know why the function about does not return the desired value for a specific input. None of the answers to Significant figures in the decimal module 解决这个问题的副本。
以下函数应该 return 具有指定有效数字位数的浮点数的字符串表示形式:
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.99999999999999954748111825886258685613938723690807819366455078125E-7。四舍五入到 5 位有效数字得到 decimal.Decimal("0.0000010000")
.
另一方面,1 可以用二进制浮点数表示,所以 1.0
正好是 1。由于只需要 1 个数字来表示十进制,上下文的精度不需要任何舍入, 你会得到一个 1 位数的十进制结果。
这是一个错误吗?我不知道,我认为文档不够严密,无法做出该决定。这当然是一个令人惊讶的结果。
可以用更多的逻辑来修复你自己的函数。
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)))