3

我依赖于一些使用 Decimal 类的代码,因为它需要精确到一定数量的小数位。一些函数允许输入是浮点数,因为它与代码库的其他部分接口的方式。要将它们转换为十进制对象,它使用类似的东西

mydec = decimal.Decimal(str(x))

其中 x 是作为输入的浮点数。我的问题是,有谁知道应用于浮动的“str”方法的标准是什么?

例如,取数字 2.1234512。由于浮点数的表示方式,它在内部存储为 2.12345119999999999。

>>> x = 2.12345119999999999
>>> x
2.1234511999999999
>>> str(x)
'2.1234512'

好的,在这种情况下,str(x) 正在执行类似 '%.6f' % x 的操作。这是我的代码转换为小数的方式的问题。采取以下措施:

>>> d = decimal.Decimal('2.12345119999999999')
>>> ds = decimal.Decimal(str(2.12345119999999999))
>>> d - ds
Decimal('-1E-17')

因此,如果我有浮点数 2.12345119999999999,并且我想将它传递给 Decimal,那么使用 str() 将其转换为字符串会得到错误的答案。我需要知道 str(x) 确定格式的规则是什么,因为我需要确定是否需要重写此代码以避免此错误(请注意,它可能没问题,因为,对于例如,一旦我们有一个小数对象,代码可能会四舍五入到小数点后 10 位)

python的文档中必须有一些规则,希望这里有人可以指出我。谢谢!

4

2 回答 2

4

在 Python 源代码中,查看“Include/floatobject.h”。字符串转换的精度设置在距顶部几行的注释之后,并对选择进行了一些解释:

/* The str() precision PyFloat_STR_PRECISION is chosen so that in most cases,
   the rounding noise created by various operations is suppressed, while
   giving plenty of precision for practical use. */

#define PyFloat_STR_PRECISION 12

如果您需要不同的东西,您可以选择重建。任何更改都会更改浮点数和复数的格式。请参见 ./Objects/complexobject.c 和 ./Objects/floatobject.c。此外,您可以比较这两个文件中 repr 和 str 如何转换双精度值的区别。

于 2013-02-25T19:02:20.380 回答
3

这里有几个问题值得讨论,但总结是:您无法提取尚未存储在系统中的信息

如果您采用十进制数并将其存储为浮点数,您将丢失信息,因为大多数具有有限位数的十进制(以 10 为底)数字不能使用以 2 为底的有限位数来存储(二进制)。

如前所述,str(a_float)真的会打电话a_float.__str__()正如文档所述,该方法的目的是

返回一个字符串,其中包含一个对象的可很好打印的表示

这种情况没有特别的定义float。我的观点是,出于您的目的,您应该考虑__str__' 的行为是undefined,因为没有关于它的官方文档 - 当前的实现可以随时更改。

如果您没有原始字符串,则无法从float对象中提取十进制表示的缺失数字。您所能做的就是使用字符串格式(您提到的)以可预测的方式进行舍入:

Decimal( "{0:.5f}".format(a_float) )

您也可以使用 删除右侧的 0 resulting_string.rstrip("0")。同样,此方法不会恢复丢失的信息。

于 2013-02-25T19:08:05.997 回答