Python Decimal不支持从float构造; 它希望你必须先将float转换为字符串.
这非常不方便,因为浮点数的标准字符串格式化程序要求您指定小数位数而不是重要位置.因此,如果你有一个数字,可能有多达15个小数位,你需要格式化为十进制(""%.15f"%my_float),如果你之前也有任何有效数字,这将给你15位小数的垃圾小数.
有人建议一个很好的方法从用户输入的浮点数转换为十进制保留值,可能会限制可支持的有效位数吗?
jfs*_*jfs 55
"%.15g" % f
Run Code Online (Sandbox Code Playgroud)
或者在Python 3.0中:
format(f, ".15g")
Run Code Online (Sandbox Code Playgroud)
只需将float Decimal直接传递给构造函数,如下所示:
from decimal import Decimal
Decimal(f)
Run Code Online (Sandbox Code Playgroud)
nos*_*klo 24
你在问题中说:
当用户输入时,有人可以建议一种从浮点数转换为十进制保留值的好方法
但每次用户输入值时,都会以字符串形式输入,而不是以浮点形式输入.你正在把它转换成某个浮点数.直接将其转换为十进制,不会丢失任何精度.
小智 13
我建议这个
>>> a = 2.111111
>>> a
2.1111110000000002
>>> str(a)
'2.111111'
>>> decimal.Decimal(str(a))
Decimal('2.111111')
Run Code Online (Sandbox Code Playgroud)
您可以转换并量化以在逗号后保留 5 位数字
Decimal(1.89977787898).quantize(Decimal("1.00000"))
Run Code Online (Sandbox Code Playgroud)
我今天遇到了同样的问题,我对迄今为止给出的任何答案都不完全满意。问题的核心似乎是:
\n\n\n有人可以建议一种从浮点转换为十进制的好方法[...]也许限制可以支持的有效数字的数量?
\n
简短的回答/解决方案:是的。
\ndef ftod(val, prec = 15):\n return Decimal(val).quantize(Decimal(10)**-prec)\nRun Code Online (Sandbox Code Playgroud)\n长答案:
\n正如 nosklo 指出的那样,在转换为浮点数后不可能保留用户的输入。\n但可以以合理的精度舍入该值并将其转换为十进制。
\n就我而言,分隔符后只需要 2 到 4 位数字,但它们需要准确。让我们考虑一下经典的 0.1 + 0.2 == 0.3 检查。
\n>>> 0.1 + 0.2 == 0.3\nFalse\nRun Code Online (Sandbox Code Playgroud)\n现在让我们通过转换为十进制来完成此操作(完整示例):
\n>>> from decimal import Decimal\n>>> def ftod(val, prec = 15): # float to Decimal\n... return Decimal(val).quantize(Decimal(10)**-prec)\n... \n>>> ftod(0.1) + ftod(0.2) == ftod(0.3)\nTrue\nRun Code Online (Sandbox Code Playgroud)\nRyabchenko Alexander 的回答对我来说非常有帮助。它只是缺少一种动态设置精度 \xe2\x80\x93 的方法,这是我想要的(也许也需要)功能。Decimal文档常见问题解答提供了有关如何构造 quantize() 所需参数字符串的示例:
\n>>> Decimal(10)**-4\nDecimal(\'0.0001\')\nRun Code Online (Sandbox Code Playgroud)\n下面是在分隔符后用 18 位数字打印的数字的样子(来自 C 编程,我喜欢花哨的 Python 表达式):
\n>>> for x in [0.1, 0.2, 0.3, ftod(0.1), ftod(0.2), ftod(0.3)]:\n... print("{:8} {:.18f}".format(type(x).__name__+":", x))\n... \nfloat: 0.100000000000000006\nfloat: 0.200000000000000011\nfloat: 0.299999999999999989\nDecimal: 0.100000000000000000\nDecimal: 0.200000000000000000\nDecimal: 0.300000000000000000\nRun Code Online (Sandbox Code Playgroud)\n最后我想知道比较的精度仍然有效:
\n>>> for p in [15, 16, 17]:\n... print("Rounding precision: {}. Check 0.1 + 0.2 == 0.3 is {}".format(p,\n... ftod(0.1, p) + ftod(0.2, p) == ftod(0.3, p)))\n... \nRounding precision: 15. Check 0.1 + 0.2 == 0.3 is True\nRounding precision: 16. Check 0.1 + 0.2 == 0.3 is True\nRounding precision: 17. Check 0.1 + 0.2 == 0.3 is False\nRun Code Online (Sandbox Code Playgroud)\n15 似乎是最大精度的默认值。这应该适用于大多数系统。如果您需要更多信息,请尝试:
\n>>> import sys\n>>> sys.float_info\nsys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)\nRun Code Online (Sandbox Code Playgroud)\n在我的系统上,浮点数有 53 位尾数,我计算了小数位数:
\n>>> import math\n>>> math.log10(2**53)\n15.954589770191003\nRun Code Online (Sandbox Code Playgroud)\n这告诉我,使用 53 位,我们几乎可以得到16 位数字。因此 15 对于精度值来说是合适的并且应该始终有效。16 容易出错,而 17 肯定会引起麻烦(如上所示)。
\n不管怎样......在我的具体情况下,我只需要 2 到 4 位的精度,但作为一个完美主义者,我喜欢研究这个:-)
\n欢迎任何建议/改进/投诉。
\n浮点数的“官方”字符串表示形式由内置的 repr() 给出:
>>> repr(1.5)
'1.5'
>>> repr(12345.678901234567890123456789)
'12345.678901234567'
Run Code Online (Sandbox Code Playgroud)
您可以使用 repr() 而不是格式化字符串,结果不会包含任何不必要的垃圾。
Python 支持从浮点数创建小数。您只需先将其转换为字符串即可。但字符串转换不会发生精度损失。您要转换的浮点数一开始就不具有这种精度。(否则你就不需要十进制)
我认为这里的困惑在于我们可以以十进制格式创建浮点文字,但是一旦解释器消耗该文字,内部表示就会变成浮点数。
| 归档时间: |
|
| 查看次数: |
66696 次 |
| 最近记录: |