truncar redondear quitar numeros los flotante decimales cortar como python floating-point rounding precision

redondear - truncar a 2 decimales python



Limitar los flotantes a dos puntos decimales (19)

Quiero que sea redondeado a 13.95 .

>>> a 13.949999999999999 >>> round(a, 2) 13.949999999999999

La función round no funciona como esperaba.


TLDR;)

El problema de redondeo en la entrada / salida se resolvió mediante Python 2.7.0 y 3.1 definitivamente.

Prueba infinita:

import random for x in iter(random.random, None): # Verify FOREVER that rounding is fixed :-) assert float(repr(x)) == x # Reversible repr() conversion. assert len(repr(round(x, 10))) <= 12 # Smart decimal places in repr() after round. if x >= 0.1: # Implicit rounding to 12 significant digits assert str(x) == repr(round(x, 12)) # by str() is good enough for small errors. y = 1000 * x # Decimal type is excessive for shopping assert str(y) == repr(round(y, 12 - 3)) # in the supermaket with Python 2.7+ :-)

Documentación

Consulte las Notas de la versión Python 2.7 - Otros idiomas cambia el cuarto párrafo:

Las conversiones entre números de punto flotante y cadenas ahora se redondean correctamente en la mayoría de las plataformas. Estas conversiones ocurren en muchos lugares diferentes: str () en flotadores y números complejos; Los constructores de flotadores y complejos; formateo numérico; serialización y deserialización de flotadores y números complejos utilizando los módulos marshal , pickle y json ; análisis de literales flotantes e imaginarios en código Python; y conversión de decimal a flotación.

En relación con esto, el repr () de un número de coma flotante x ahora devuelve un resultado basado en la cadena decimal más corta que se garantiza redondear de nuevo a x en el redondeo correcto (con el modo de redondeo de la mitad a la mitad). Anteriormente, daba una cadena basada en el redondeo de x a 17 dígitos decimales.

El tema relacionado

Más información:: el formato de float antes de Python 2.7 era similar al número actual. Ambos tipos utilizan la misma doble precisión IEEE 754 de 64 bits con una mantisa de 52 bits. Una gran diferencia es que np.float64.__repr__ se formatea con frecuencia con un número decimal excesivo para que no se pierda ningún bit, pero no existe un número IEEE 754 válido entre 13.949999999999999 y 13.950000000000001. El resultado no es bueno y la conversión repr(float(number_as_string)) no es reversible. Por otro lado: float.__repr__ está formateado para que cada dígito sea importante; La secuencia es sin huecos y la conversión es reversible. Simplemente: si tiene un número numpy.float64, conviértalo a flotación normal para que se formatee para humanos, no para procesadores numéricos, de lo contrario no es necesario nada más con Python 2.7+.


Como señaló @Matt, Python 3.6 proporciona f-strings , y también pueden usar parámetros anidados :

value = 2.34558 precision = 2 width = 4 print(f''result: {value:{width}.{precision}f}'')

que mostrará el result: 2.35


Con Python <3 (por ejemplo, 2.6 o 2.7), hay dos formas de hacerlo.

# Option one older_method_string = "%.9f" % numvar # Option two (note '':'' before the ''.9f'') newer_method_string = "{:.9f}".format(numvar)

Pero tenga en cuenta que para las versiones de Python superiores a 3 (por ejemplo, 3.2 o 3.3), se preferred opción dos.

Para obtener más información sobre la opción dos, sugiero este enlace en el formato de cadena de la documentación de Python .

Y para obtener más información sobre la opción uno, este enlace será suficiente y contiene información sobre los distintos indicadores .

Referencia: Convierta el número de punto flotante a una cierta precisión, y luego cópielo a la cadena


El round() integrado funciona bien en Python 2.7 o posterior.

Ejemplo:

>>> round(14.22222223, 2) 14.22

Echa un vistazo a la documentación .


El método que utilizo es el de corte de cadena. Es relativamente rápido y simple.

Primero, convierta el flotador en una cadena, elija la longitud que desea que sea.

float = str(float)[:5]

En la línea única de arriba, hemos convertido el valor en una cadena, luego conservamos la cadena solo en sus primeros cuatro dígitos o caracteres (inclusive).

¡Espero que ayude!


El tutorial de Python tiene un apéndice llamado Aritmética de punto flotante: problemas y limitaciones . Leerlo Explica lo que está sucediendo y por qué Python está haciendo todo lo posible. Incluso tiene un ejemplo que coincide con el tuyo. Déjame citar un poco:

>>> 0.1 0.10000000000000001

puede tener la tentación de usar la función round() para recortarla al dígito que espera. Pero eso no hace ninguna diferencia:

>>> round(0.1, 1) 0.10000000000000001

El problema es que el valor binario de punto flotante almacenado para “0.1” ya era la mejor aproximación binaria posible a 1/10 , por lo que tratar de redondearlo de nuevo no puede mejorarlo: ya era tan bueno como es.

Otra consecuencia es que dado que 0.1 no es exactamente 1/10 , sumar diez valores de 0.1 puede no producir exactamente 1.0 , ya sea:

>>> sum = 0.0 >>> for i in range(10): ... sum += 0.1 ... >>> sum 0.99999999999999989

Una alternativa y solución a sus problemas sería utilizar el módulo decimal .


En Python 2.7:

a = 13.949999999999999 output = float("%0.2f"%a) print output


Está haciendo exactamente lo que le dijiste que hiciera y está funcionando correctamente. Lea más sobre la confusión de punto flotante y quizás intente objetos decimal lugar.


Hay nuevas especificaciones de formato, Mini-lenguaje de especificación de formato de cadena :

Puedes hacer lo mismo que:

"{0:.2f}".format(13.949999999999999)

Tenga en cuenta que lo anterior devuelve una cadena. Para obtener el flotador, simplemente envuélvalo con float(...) :

float("{0:.2f}".format(13.949999999999999))

Tenga en cuenta que envolver con float() no cambia nada:

>>> x = 13.949999999999999999 >>> x 13.95 >>> g = float("{0:.2f}".format(x)) >>> g 13.95 >>> x == g True >>> h = round(x, 2) >>> h 13.95 >>> x == h True


La mayoría de los números no pueden ser representados exactamente en flotadores. Si desea redondear el número porque eso es lo que requiere su fórmula matemática o algoritmo, entonces quiere usar la ronda. Si solo desea restringir la visualización a una cierta precisión, entonces ni siquiera use redondear y simplemente formatee como esa cadena. (Si desea mostrarlo con algún método de redondeo alternativo, y hay toneladas, entonces necesita mezclar los dos enfoques).

>>> "%.2f" % 3.14159 ''3.14'' >>> "%.2f" % 13.9499999 ''13.95''

Y, por último, aunque quizás lo más importante, si quieres cálculos exactos , entonces no quieres flotadores en absoluto. El ejemplo habitual es tratar con dinero y almacenar ''centavos'' como un entero.


Para corregir el punto flotante en lenguajes de tipo dinámico como Python y JavaScript, utilizo esta técnica

# For example: a = 70000 b = 0.14 c = a * b print c # Prints 980.0000000002 # Try to fix c = int(c * 10000)/100000 print c # Prints 980

También puedes usar decimal como sigue:

from decimal import * getcontext().prec = 6 Decimal(1) / Decimal(7) # Results in 6 precision -> Decimal(''0.142857'') getcontext().prec = 28 Decimal(1) / Decimal(7) # Results in 28 precision -> Decimal(''0.1428571428571428571428571429'')


Para redondear un número a una resolución, la mejor manera es la siguiente, que puede funcionar con cualquier resolución (0.01 para dos decimales o incluso otros pasos):

>>> import numpy as np >>> value = 13.949999999999999 >>> resolution = 0.01 >>> newValue = int(np.round(value/resolution))*resolution >>> print newValue 13.95 >>> resolution = 0.5 >>> newValue = int(np.round(value/resolution))*resolution >>> print newValue 14.0


Parece que nadie aquí lo ha mencionado todavía, así que déjeme dar un ejemplo en el formato f-string / template-string de Python 3.6, que creo que es muy bonito:

>>> f''{a:.2f}''

También funciona bien con ejemplos más largos, con operadores y sin necesidad de parens:

>>> print(f''Completed in {time.time() - start:.2f}s'')


Pruebe el siguiente código:

>>> a = 0.99334 >>> a = int((a * 100) + 0.5) / 100.0 # Adding 0.5 rounds it up >>> print a 0.99


Puede modificar el formato de salida:

>>> a = 13.95 >>> a 13.949999999999999 >>> print "%.2f" % a 13.95


Se está encontrando en el problema anterior con los números de punto flotante que todos los números no pueden ser representados. La línea de comando solo muestra la forma de punto flotante completa de la memoria.

En punto flotante su versión redondeada es el mismo número. Como las computadoras son binarias, almacenan números de punto flotante como un número entero y luego lo dividen por una potencia de dos, por lo que 13.95 se representará de manera similar a 125650429603636838 / (2 ** 53).

Los números de precisión doble tienen 53 bits (16 dígitos) de precisión y los flotadores regulares tienen 24 bits (8 dígitos) de precisión. El punto flotante en Python utiliza doble precisión para almacenar los valores.

Por ejemplo,

>>> 125650429603636838/(2**53) 13.949999999999999 >>> 234042163/(2**24) 13.949999988079071 >>> a=13.946 >>> print(a) 13.946 >>> print("%.2f" % a) 13.95 >>> round(a,2) 13.949999999999999 >>> print("%.2f" % round(a,2)) 13.95 >>> print("{0:.2f}".format(a)) 13.95 >>> print("{0:.2f}".format(round(a,2))) 13.95 >>> print("{0:.15f}".format(round(a,2))) 13.949999999999999

Si busca solo dos lugares decimales en moneda, entonces tiene un par de mejores opciones: 1) Use números enteros y almacene valores en centavos, no en dólares y luego divida por 100 para convertir a dólares. 2) O usa un número de punto fijo como decimal .


Siento que el enfoque más simple es usar la función format() .

Por ejemplo:

a = 13.949999999999999 format(a, ''.2f'') 13.95

Esto produce un número flotante como una cadena redondeada a dos puntos decimales.


Utilizar

print"{:.2f}".format(a)

en lugar de

print"{0:.2f}".format(a)

Debido a que esto último puede llevar a errores de salida al intentar generar múltiples variables (ver comentarios).


orig_float = 232569 / 16000.0

14.5355625

short_float = float("{:.2f}".format(orig_float))

14.54