print - python truncate float
Figuras significativas en el módulo decimal (6)
¿Qué pasa con el punto flotante?
>>> "%8.2e"% ( 1.0/3.0 )
''3.33e-01''
Fue diseñado para cálculos de estilo científico con un número limitado de dígitos significativos.
Así que decidí intentar resolver mi tarea de física escribiendo algunos scripts de Python para resolver problemas. Un problema con el que me estoy metiendo es que las cifras significativas no siempre salen bien. Por ejemplo, esto maneja cifras significativas correctamente:
from decimal import Decimal
>>> Decimal(''1.0'') + Decimal(''2.0'')
Decimal("3.0")
Pero esto no:
>>> Decimal(''1.00'') / Decimal(''3.00'')
Decimal("0.3333333333333333333333333333")
Entonces dos preguntas:
- ¿Estoy en lo correcto al decir que esta no es la cantidad esperada de dígitos significativos, o necesito repasar los cálculos matemáticos significativos?
- ¿Hay alguna manera de hacerlo sin tener que establecer la precisión decimal manualmente? De acuerdo, estoy seguro de que puedo usar Numpy para hacer esto, pero solo quiero saber si hay una manera de hacerlo con el módulo decimal por curiosidad.
Cambiar la precisión de trabajo decimal a 2 dígitos no es una buena idea, a menos que solo realice absolutamente una sola operación.
Siempre debe realizar cálculos con una precisión mayor que el nivel de significancia, y solo alrededor del resultado final. Si realiza una secuencia larga de cálculos y redondea la cantidad de dígitos significativos en cada paso, los errores se acumularán. El módulo decimal no sabe si una operación en particular es una en una secuencia larga, o el resultado final, por lo que asume que no debe redondear más de lo necesario. Idealmente, utilizaría una precisión infinita, pero eso es demasiado caro, por lo que los desarrolladores de Python se conformaron con 28 dígitos.
Una vez que ha llegado al resultado final, lo que probablemente quiera es cuantizar:
>>> (Decimal(''1.00'') / Decimal(''3.00'')).quantize(Decimal("0.001")) Decimal("0.333")
Debe realizar un seguimiento de la importancia de forma manual. Si desea un seguimiento de significancia automático, debe usar la aritmética de intervalos. Hay algunas bibliotecas disponibles para Python, incluyendo pyinterval y mpmath (que admite una precisión arbitraria). También es sencillo implementar la aritmética de intervalos con la biblioteca decimal, ya que admite el redondeo dirigido.
También puede leer las Preguntas Frecuentes de Aritmética Decimal: ¿La aritmética decimal es aritmética?
El decimal está predeterminado en 28 lugares de precisión.
La única manera de limitar la cantidad de dígitos que devuelve es alterando la precisión.
Los decimales no arrojarán decimales como ese. Si realmente quieres limitar la precisión a 2 dp, prueba
decimal.getcontext().prec=2
EDITAR: alternativamente puede llamar a quantize () cada vez que multiplica o divide (la suma y la resta conservarán los 2 dps).
Si entiendo Decimal correctamente, la "precisión" es el número de dígitos después del punto decimal en notación decimal .
Parece que quiere algo más: la cantidad de dígitos significativos. Eso es uno más que el número de dígitos después del punto decimal en la notación científica .
Me interesaría aprender sobre un módulo de Python que hace cálculos de punto flotante conscientes de los dígitos significativos.
Solo por curiosidad ... ¿es necesario usar el módulo decimal? ¿Por qué no el punto flotante con un redondeo de números de cifras significativas cuando estás listo para verlos? ¿O está tratando de realizar un seguimiento de las cifras significativas del cálculo (como cuando tiene que hacer un análisis de error de un resultado, calcular el error calculado en función de las incertidumbres que entraron en el cálculo)? Si desea una función de redondeo que se desplace desde la izquierda del número en lugar de la derecha, intente:
def lround(x,leadingDigits=0):
"""Return x either as ''print'' would show it (the default)
or rounded to the specified digit as counted from the leftmost
non-zero digit of the number, e.g. lround(0.00326,2) --> 0.0033
"""
assert leadingDigits>=0
if leadingDigits==0:
return float(str(x)) #just give it back like ''print'' would give it
return float(''%.*e'' % (int(leadingDigits),x)) #give it back as rounded by the %e format
Los números se verán correctamente cuando los imprima o los convierta en cadenas, pero si está trabajando en el indicador y no los imprime explícitamente, pueden parecer un poco extraños:
>>> lround(1./3.,2),str(lround(1./3.,2)),str(lround(1./3.,4))
(0.33000000000000002, ''0.33'', ''0.3333'')