Python float to Decimal conversion

家住魔仙堡 提交于 2019-12-18 01:19:22

问题


Python Decimal doesn't support being constructed from float; it expects that you have to convert float to a string first.

This is very inconvenient since standard string formatters for float require that you specify number of decimal places rather than significant places. So if you have a number that could have as many as 15 decimal places you need to format as Decimal(""%.15f"% my_float), which will give you garbage at the 15th decimal place if you also have any significant digits before decimal.

Can someone suggest a good way to convert from float to Decimal preserving value as the user has entered, perhaps limiting number of significant digits that can be supported?


回答1:


Python <2.7

"%.15g" % f

Or in Python 3.0:

format(f, ".15g")

Python 2.7+, 3.2+

Just pass the float to Decimal constructor directly, like this:

from decimal import Decimal
Decimal(f)



回答2:


You said in your question:

Can someone suggest a good way to convert from float to Decimal preserving value as the user has entered

But every time the user enters a value, it is entered as a string, not as a float. You are converting it to a float somewhere. Convert it to a Decimal directly instead and no precision will be lost.




回答3:


I suggest this

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



回答4:


Python does support Decimal creation from a float. You just cast it as a string first. But the precision loss doesn't occur with string conversion. The float you are converting doesn't have that kind of precision in the first place. (Otherwise you wouldn't need Decimal)

I think the confusion here is that we can create float literals in decimal format, but as soon as the interpreter consumes that literal the inner representation becomes a floating point number.




回答5:


The "official" string representation of a float is given by the repr() built-in:

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

You can use repr() instead of a formatted string, the result won't contain any unnecessary garbage.




回答6:


When you say "preserving value as the user has entered", why not just store the user-entered value as a string, and pass that to the Decimal constructor?




回答7:


The "right" way to do this was documented in 1990 by Steele and White's and Clinger's PLDI 1990 papers.

You might also look at this SO discussion about Python Decimal, including my suggestion to try using something like frap to rationalize a float.



来源:https://stackoverflow.com/questions/316238/python-float-to-decimal-conversion

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!