Python浮动到十进制转换

时间:2008-11-25 02:53:44

标签: python decimal

Python Decimal不支持从float构造;它希望你必须先将float转换为字符串。

这非常不方便,因为float的标准字符串格式化程序要求您指定小数位数而不是重要位置。因此,如果你有一个数字,可能有多达15个小数位,你需要格式化为十进制(“”%。15f“%my_float),如果你之前也有任何有效数字,这将给你15位小数的垃圾小数。

有人建议用户输入时从浮点数转换为十进制保留值的好方法,可能会限制可支持的有效位数吗?

10 个答案:

答案 0 :(得分:49)

Python< 2.7

"%.15g" % f

或者在Python 3.0中:

format(f, ".15g")

Python 2.7 +,3.2 +

直接将float传递给Decimal构造函数,如下所示:

from decimal import Decimal
Decimal(f)

答案 1 :(得分:23)

你在问题​​中说:

  

有人可以建议一个好方法   从float转换为Decimal   保留用户拥有的价值   输入

但每次用户输入值时,都会以字符串形式输入,而不是以浮点形式输入。你正在把它转换成某个浮点数。直接将其转换为十进制,不会丢失任何精度。

答案 2 :(得分:10)

我建议这个

>>> a = 2.111111
>>> a
2.1111110000000002
>>> str(a)
'2.111111'
>>> decimal.Decimal(str(a))
Decimal('2.111111')

答案 3 :(得分:4)

Python确实支持从float创建Decimal。你只需先把它作为一个字符串。但是字符串转换不会发生精度损失。您正在转换的浮点数首先没有那种精度。 (否则你不需要十进制)

我认为这里的混淆是我们可以用十进制格式创建浮点文字,但只要解释器​​使用该文字,内部表示就会成为一个浮点数。

答案 4 :(得分:3)

float的“官方”字符串表示由内置的repr()给出:

>>> repr(1.5)
'1.5'
>>> repr(12345.678901234567890123456789)
'12345.678901234567'

您可以使用repr()而不是格式化的字符串,结果将不包含任何不必要的垃圾。

答案 5 :(得分:2)

当您说“保留用户输入的值”时,为什么不将用户输入的值存储为字符串,并将其传递给Decimal构造函数?

答案 6 :(得分:0)

1990年Steele and White's and Clinger's PLDI 1990论文记录了这种“正确”的做法。

您也可以查看this关于Python Decimal的讨论,包括我建议尝试使用类似frap的内容来合理化浮点数。

答案 7 :(得分:0)

您可以使用JSON完成

import json
from decimal import Decimal

float_value = 123456.2365
decimal_value = json.loads(json.dumps(float_value), parse_float=Decimal)

答案 8 :(得分:0)

主要答案有些误导。 g格式会忽略小数点后的任何前导零,因此format(0.012345, ".2g")返回0.012-小数点后三位。如果您需要硬限制小数位数,请使用f格式程序:format(0.012345, ".2f") == 0.01

答案 9 :(得分:0)

受到 this answer 的启发,我找到了一种解决方法,该方法允许从绕过(仅明显)string 步骤的浮点数缩短 Decimal 的构造:

import decimal
class DecimalBuilder(float):
    def __or__(self, a):
         return decimal.Decimal(str(a))

>>> d = DecimalBuilder()
>>> x = d|0.1
>>> y = d|0.2
>>> x + y # works as desired
Decimal('0.3')
>>> d|0.1 + d|0.2 # does not work as desired, needs parenthesis
TypeError: unsupported operand type(s) for |: 'decimal.Decimal' and 'float'
>>> (d|0.1) + (d|0.2) # works as desired
Decimal('0.3')

这是一种解决方法,但它确实可以节省代码输入,而且可读性很强。