在Python 2.6中如何将float转换为Decimal,以及为什么没有实现

14 投票
3 回答
9013 浏览
提问于 2025-04-17 05:35

在Python 2.7中,浮点数(float)可以直接转换成十进制数(Decimal),这在Decimal的构造函数和Decimal.from_float()这个类方法中都有实现。

而在Python 2.6中,如果你尝试这样做,就会出现一个类型错误(TypeError),提示你先把浮点数转换成字符串:

TypeError: Cannot convert float to Decimal.  First convert the float to a string

所以我通常的解决办法是这样的:

if sys.version_info < (2, 7):
    Decimal.from_float = classmethod(lambda cls, x: cls(str(x)))

这只是对错误信息的字面翻译而已——我也懒得在构造函数中实现这个方法。

如果这么简单,为什么一开始不直接实现呢,而是让用户在出现类型错误时去处理?这真的是最好的方法吗?(那么在Python 2.7及更新版本中也是这样吗?)

3 个回答

0

根据2.7版本的新特性文档(特别强调一下)

在大多数平台上,浮点数和字符串之间的转换现在可以正确四舍五入了。这种转换发生在很多地方:比如把浮点数和复数用str()转换成字符串;使用float和complex构造函数;数字格式化;使用marshal、pickle和json模块对浮点数和复数进行序列化和反序列化;在Python代码中解析浮点数和虚数;还有十进制数转浮点数的转换。

所以,虽然在2.7之前他们本来可以做到这一点,但显然因为之前存在的四舍五入问题,他们并不太敢这样做。

4

可能是因为直接转换的行为如果你不知道一些关于浮点数的实现细节,会让人感到困惑。正如文档中所说的:

注意,Decimal.from_float(0.1)Decimal('0.1') 是不一样的。因为 0.1 在二进制浮点数中并不能被准确表示,所以它存储的是最接近的可表示值,也就是 0x1.999999999999ap-4。这个值用十进制表示就是 0.1000000000000000055511151231257827021181583404541015625

如果你把它转换成字符串,你可以控制想要的精度,这样就能准确地转换成 Decimal

这个新方法是在 Python 2.7 中引入的,所以在 2.6 版本中没有。新功能不会被移植到旧版本。

11

你的解决方法并不是正确的做法,因为这样会丢失一些信息。正确的无损转换方法可以在 float_to_decimal() 的说明中找到,具体内容可以查看 Decimal常见问题解答

我们在Python 2.6中没有加入Decimal.from_float这个功能,是因为我们想谨慎一点,避免二进制浮点数和十进制浮点数之间产生意外的相互影响。到了Python 2.7,这个问题已经解决了,你只需要写 Decimal(f),其中f是一个二进制浮点数。

除了在2.6版本中的小麻烦之外,希望你能喜欢Decimal模块。

撰写回答