Python Decimal不支持从float构造;它希望你必须先将float转换为字符串。
这非常不方便,因为float的标准字符串格式化程序要求您指定小数位数而不是重要位置。因此,如果你有一个数字,可能有多达15个小数位,你需要格式化为十进制(“”%。15f“%my_float),如果你之前也有任何有效数字,这将给你15位小数的垃圾小数。
有人建议用户输入时从浮点数转换为十进制保留值的好方法,可能会限制可支持的有效位数吗?
答案 0 :(得分:49)
"%.15g" % f
或者在Python 3.0中:
format(f, ".15g")
直接将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论文记录了这种“正确”的做法。
答案 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')
这是一种解决方法,但它确实可以节省代码输入,而且可读性很强。