Problemas con redondear decimales (python)

En mi progtwig, la precisión decimal es muy importante.
Muchos de mis cálculos deben ser precisos con muchos decimales (como 50).

Debido a que estoy usando python, he estado usando el módulo decimal (con context (). Prec = 99. es decir, configurado para tener 99 lugares decimales de precisión al crear una instancia de un objeto decimal )
Como los flotadores pythonic no permiten ningún tipo de precisión.

Como deseo que el Usuario especifique los lugares decimales de precisión de los cálculos, he tenido que implementar varias funciones round () en mi código.
Desafortunadamente, la función de redondeo incorporada y el objeto decimal no interactúan bien.

round(decimal.Decimal('2.000000000000000000001'),50) # Number is 1e-21. There are 21 decimal places, much less than 50. 

Sin embargo, el resultado es 2.0 en lugar de 2.000000000000000000001
La función de redondeo no es redondear a 50. ¡Mucho menos!

Sí, me he asegurado de que el redondeo no se produzca en la creación de instancias del objeto decimal, sino después de la ronda de llamadas.
Siempre paso cadenas que representan flotadores al constructor decimal, nunca flotadores pythonic.

¿Por qué la función redonda me está haciendo esto?
(Me doy cuenta de que probablemente fue diseñado originalmente para flotadores pythonic que nunca pueden tener tantos lugares decimales, pero la documentación afirma que el objeto decimal se integra perfectamente en el código de python y es compatible con las funciones incorporadas de python).

¡Gracias profusamente!
(Esto me tiene bastante nervioso, ya que este problema socava el uso de todo el progtwig)

Especificaciones:
python 2.7.1
Windows 7
módulo decimal (incorporado)

El problema, tan cerca como puedo determinarlo, es que round() está devolviendo un tipo float Python, y no un tipo Decimal . Por lo tanto, no importa la precisión que establezca en el módulo decimal , porque una vez que llama a round() ya no tiene un Decimal .

Para solucionar esto, probablemente tendrá que encontrar una forma alternativa de redondear sus números que no se base en round() . Como la sugerencia de Raymond.

Puede encontrar este ejemplo breve de ideone ilustrativo: http://ideone.com/xgPL9

Como round () obliga a su entrada a un flotador binario regular, la forma preferida de redondear objetos decimales es con el método de cuantización () :

 >>> from decimal import Decimal >>> d = Decimal('2.000000000000000000001') >>> d.quantize(Decimal(10) ** -20) # Round to twenty decimal places Decimal('2.00000000000000000000') 

Para cortar los ceros finales, aplique normalize () al resultado redondeado:

 >>> d = Decimal('2.000000000000000000001') >>> d.quantize(Decimal(10) ** -20).normalize() Decimal('2') 

Usar round() para cualquier propósito tiene dificultades:

(1) En Python 2.7, round (Decimal (’39 .142 ‘)) produce 39.14, es decir, un flotador; 3.2 produce un decimal.

 >>> import decimal; round(decimal.Decimal('2.000000000000000000001'),50) 2.0 <<<=== ***float*** 

(2) round () tiene solo un modo de redondeo; Decimal.quantize tiene muchos.

(3) Para todos los tipos de entrada, el modo de redondeo único cambió: Python 2.7 se redondea fuera de 0 (esperado en la mayoría de las aplicaciones comerciales), mientras que Python 3.2 se redondea al múltiplo más cercano de 10 ** - n (menos esperado en el negocio).

Usa Decimal.quantize()

Intenta lo siguiente …

 from decimal import Decimal, ROUND_HALF_UP, getcontext getcontext().prec = 51 def round_as_decimal(num, decimal_places=2): """Round a number to a given precision and return as a Decimal Arguments: :param num: number :type num: int, float, decimal, or str :returns: Rounded Decimal :rtype: decimal.Decimal """ precision = '1.{places}'.format(places='0' * decimal_places) return Decimal(str(num)).quantize(Decimal(precision), rounding=ROUND_HALF_UP) round_as_decimal('2.000000000000000000001', decimal_places=50) 

¡Espero que ayude!

Como se indicó anteriormente, round () devuelve un valor flotante si se le proporciona un decimal. Para cálculos exactos, sugiero hacerlos con decimales no redondeados, y para redondear el resultado final, use una función:

  def dround(decimal_number, decimal_places): return decimal_number.quantize(Decimal(10) ** -decimal_places)