Python Decimal ne prend pas en charge la construction à partir de float; il s'attend à ce que vous deviez d'abord convertir float en chaîne.
Ceci est très gênant car les formateurs de chaîne standard pour float nécessitent que vous spécifiez un nombre de décimales plutôt que des emplacements significatifs. Donc, si vous avez un nombre pouvant contenir jusqu'à 15 décimales, vous devez formater en décimal (""%. 15f "% my_float), ce qui vous donnera des ordures à la 15e décimale si vous avez également des chiffres significatifs avant décimal.
Quelqu'un peut-il suggérer un bon moyen de convertir de float en valeur décimale en préservant que l'utilisateur a entré, peut-être en limitant le nombre de chiffres significatifs qui peuvent être pris en charge?
"%.15g" % f
Ou en Python 3.0:
format(f, ".15g")
Passez simplement le float au constructeur Decimal
directement, comme ceci:
from decimal import Decimal
Decimal(f)
Vous avez dit dans votre question:
Quelqu'un peut-il suggérer un bon moyen de convertir un flottant en décimal en préservant la valeur telle que l'utilisateur l'a saisie
Mais chaque fois que l'utilisateur entre une valeur, celle-ci est entrée sous forme de chaîne et non sous forme de flottant. Vous le convertissez quelque part en flotteur. Convertissez-le directement en décimal à la place et aucune précision ne sera perdue.
Je propose ceci
>>> a = 2.111111
>>> a
2.1111110000000002
>>> str(a)
'2.111111'
>>> decimal.Decimal(str(a))
Decimal('2.111111')
Python prend en charge la création décimale à partir d'un flottant. Vous venez de le lancer comme une chaîne en premier. Mais la perte de précision ne se produit pas avec la conversion de chaînes. Le flotteur que vous convertissez n'a pas ce genre de précision en premier lieu. (Sinon, vous n'auriez pas besoin de Decimal)
Je pense que la confusion ici est que nous pouvons créer des littéraux flottants au format décimal, mais dès que l'interpréteur consomme ce littéral, la représentation interne devient un nombre à virgule flottante.
La représentation "officielle" sous forme de chaîne d'un flottant est donnée par le repr () intégré:
>>> repr(1.5)
'1.5'
>>> repr(12345.678901234567890123456789)
'12345.678901234567'
Vous pouvez utiliser repr () au lieu d'une chaîne formatée, le résultat ne contiendra pas de déchets inutiles.
Lorsque vous dites "conserver la valeur telle que l'utilisateur l'a saisie", pourquoi ne pas simplement stocker la valeur entrée par l'utilisateur sous forme de chaîne et la transmettre au constructeur Decimal?
La "bonne" façon de procéder a été documentée en 1990 par Steele et White et Clinger's PLDI 199 papiers.
Vous pouvez également consulter ceci SO discussion sur Python Decimal, y compris ma suggestion d'essayer d'utiliser quelque chose comme frap pour rationaliser un flottant.