2008-09-11 24 views
93

La documentación para la función round() indica que le pasa un número y las posiciones pasan del decimal al redondeo. Por lo tanto, debe hacer esto:round() en Python no parece estar redondeando correctamente

n = 5.59 
round(n, 1) # 5.6 

Pero, en realidad, un buen punto flotante rareza de edad se arrastra y se obtiene:

5.5999999999999996 

A los efectos de la interfaz de usuario, que necesita mostrar 5.6. Busqué en Internet y encontré algunos documentation que esto depende de mi implementación de Python. Desafortunadamente, esto ocurre tanto en mi máquina de desarrollo de Windows como en cada servidor Linux que he probado. See here also.

A falta de crear mi propia biblioteca redonda, ¿hay alguna forma de evitar esto?

+2

yo probamos este con el pitón 2.7.11 redonda (5,59) y que está dando como resultado 5.6 en ambas ventanas y linux x86 máquina de 64 bit, Cython? (El enlace de documentación mencionado ahora se cambia) supongo) –

+0

Donde en realidad no funciona correctamente es 'redondo (5.55, 1) = 5.5'. – Dmitry

Respuesta

88

no puede ayudar a la forma en que se almacena, pero al menos el formato funciona correctamente:

'%.1f' % round(n, 1) # gives you '5.6' 
+5

probé 'print '% .2f'% 655.665' pero devuelve' 655.66', debería ser '655.67' – Kyrie

+1

@Kyrie ver http://stackoverflow.com/questions/9301690/python-float-round-error- 117-285-round-to-117-28-not-117-29. La imprecisión del punto flotante es la culpable aquí: "5.665 -> 5.67" pero "15.665 -> 15.66". Use decimales si necesita precisión exacta. – Jimmy

+5

esto está funcionando después de la búsqueda :) 'de la importación decimal Decimal, ROUND_HALF_UP, ROUND_HALF_DOWN' # uso al redondear números flotantes ' Decimal (str (655.665)). Quantize (Decimal ('1.11'), redondeo = ROUND_HALF_UP) '# Issues y Limitaciones en puntos flotantes – Kyrie

-4

¿Qué hay de:

round(n,1)+epsilon 
+0

Eso solo funcionaría si el redondeo fuera constantemente del número redondo por épsilon. Si 'epsilon = .000001' luego' round (1.0/5.0, 1) + epsilon' toma la representación exacta 0.2 y la convierte en 0.00001. Igualmente malos problemas ocurrirían si el épsilon estuviera dentro de la función de ronda. –

7

Se puede cambiar el tipo de datos a un número entero:

>>> n = 5.59 
>>> int(n * 10)/10.0 
5.5 
>>> int(n * 10 + 0.5) 
56 

Y a continuación, muestre el número insertando el separador decimal de la configuración regional.

Sin embargo, Jimmy's answer es mejor.

+0

¡Parece el método más robusto! – buzhidao

3

Puede usar el operador de formato de cadena %, similar al sprintf.

mystring = "%.2f" % 5.5999 
11

se obtiene el '5.6' si lo hace str(round(n, 1)) en lugar de sólo round(n, 1).

5

La matemática de coma flotante es vulnerable a ligeras, pero molestas, imprecisiones de precisión. Si puede trabajar con un número entero o punto fijo, se le garantizará precisión.

3

printf la ventosa.

print '%.1f' % 5.59 # returns 5.6 
92

Formateo funciona correctamente incluso sin tener que ronda:

"%.1f" % n 
+11

De acuerdo con [los documentos] (https://docs.python.org/3.2/tutorial/inputoutput.html#old-string-formatting), este estilo de formato de cadenas eventualmente desaparecerá. El formato de estilo nuevo sería '" {: .1f} ". Format (n)' – whereswalden

+1

No redondea correctamente: ''% .5f'% 0.988625' da' 0.98862' – schlamar

+0

@schlamar: Eso es round() 's comportamiento también: redondo (0.988625,5) también da 0.98862. round (0.988626,5) así como "% .5f"% 0.988626 give 0.98863 –

18

round(5.59, 1) es trabajar muy bien. El problema es que 5.6 no se puede representar exactamente en el punto flotante binario.

>>> 5.6 
5.5999999999999996 
>>> 

Como dice Vinko, puede usar el formateo de cadenas para redondear la pantalla.

Python tiene un module for decimal arithmetic si lo necesita.

+1

Esto no es l ya es un problema con Python 2.7 o Python 3.5 – vy32

4

Tome un vistazo a la Decimal module

decimal “se basa en un punto flotante modelo que fue diseñado con la gente en mente, y necesariamente tiene un principio rector primordial - equipos deben proporcionar una aritmética que funciona de la misma manera que la aritmética que las personas aprenden en escuela. "- extracto de la especificación aritmética decimal .

y

Los números decimales pueden representarse exactamente . Por el contrario, los números como 1.1 y 2.2 no tienen una representación exacta de en el punto flotante binario. Los usuarios finales normalmente no esperan que 1.1 + 2.2 se muestre como 3.3000000000000003 como lo hace con el punto flotante binario.

decimal proporciona el tipo de operaciones que hacen que sea fácil de escribir aplicaciones que requieren operaciones de punto flotante y también necesidad de presentar los resultados en un formato legible por humanos, por ejemplo, la contabilidad.

19

Si utiliza el módulo Decimal puede aproximar sin el uso de la función 'ronda'. Esto es lo que he estado utilizando para el redondeo especialmente cuando la escritura de aplicaciones monetarias:

Decimal(str(16.2)).quantize(Decimal('.01'), rounding=ROUND_UP) 

Esto devolverá un número decimal que es 16.20.

+0

Esta es la respuesta realmente inteligente. – Rockallite

+2

** Esta es la respuesta canónica **, donde la precisión importa, de todos modos, que está prácticamente en todas partes. Claro: _es un poco verboso_. Pero tira ese tonto en una función auxiliar y estarás listo para formatear e ir. –

2

De hecho, es un gran problema. Pruebe este código:

print "%.2f" % (round((2*4.4+3*5.6+3*4.4)/8,2),) 

Muestra 4.85. Luego lo hace:

print "Media = %.1f" % (round((2*4.4+3*5.6+3*4.4)/8,1),) 

y muestra 4.8. Hacer cálculos a mano que la respuesta exacta es 4,85, pero si intenta:

print "Media = %.20f" % (round((2*4.4+3*5.6+3*4.4)/8,20),) 

se puede ver la verdad: el punto flotante se almacena como la suma finita más cercana de las fracciones cuyos denominadores son potencias de dos.

2

funciona perfecto

format(5.59, '.1f') # to display 
float(format(5.59, '.1f')) #to round 
1

que estoy haciendo:

int(round(x , 0)) 

En este caso, la primera ronda adecuadamente a nivel de unidad, entonces convertimos a entero para evitar la impresión de un flotador.

por lo

>>> int(round(5.59,0)) 
6 

Creo que esta respuesta funciona mejor que formatear la cadena, y también hace más sens me utilizar la función de ronda.

0

Aquí es donde veo el fracaso redondo. ¿Qué pasaría si quisieras redondear estos 2 números a un decimal? 23.45 23.55 Mi educación fue que a partir de estos redondeo que debe obtener: 23,4 23,6 la "regla" es que se debe redondear al alza si el número anterior era impar, no redondear al alza si el número anterior eran aún. La función de redondeo en Python simplemente trunca el Código 5.

+1

Lo que estás diciendo es ["redondeo bancario"] (https://en.wikipedia.org/wiki/Rounding), una de las muchas maneras diferentes de realizar el redondeo. –

+0

Esto no proporciona una respuesta a la pregunta. Una vez que tenga suficiente [reputación] (https://stackoverflow.com/help/whats-reputation) podrá [comentar cualquier publicación] (https://stackoverflow.com/help/privileges/comment); en su lugar, [brinde respuestas que no requieran aclaración del autor de la pregunta] (https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can- i-do-instead). - [De la crítica] (/ crítica/mensajes de baja calidad/18895739) – Ilkka

0

:

x1 = 5.63 
x2 = 5.65 
print(float('%.2f' % round(x1,1))) # gives you '5.6' 
print(float('%.2f' % round(x2,1))) # gives you '5.7' 

Salida:

5.6 
5.7 
Cuestiones relacionadas