round float down decimals python python-3.x rounding

float - round python



Comportamiento de redondeo de Python 3.x (5)

Comportamiento de redondeo de Python 2 en python 3.

Sumando 1 en los decimales lugares decimales. Precisión hasta 15 dígitos.

round2=lambda x,y=None: round(x+1e-15,y)

Estaba volviendo a leer Lo nuevo en Python 3.0 y dice:

La estrategia de redondeo de la función round () y el tipo de retorno han cambiado. Los casos de mitad de camino exactos ahora se redondean al resultado par más cercano en lugar de alejarse de cero. (Por ejemplo, round (2.5) ahora devuelve 2 en lugar de 3.)

y la documentación para la round :

Para los tipos incorporados que soportan round (), los valores se redondean al múltiplo más cercano de 10 a la potencia menos n; si dos múltiplos son igualmente cercanos, el redondeo se realiza hacia la elección pareja

Entonces, en v2.7.3 :

In [85]: round(2.5) Out[85]: 3.0 In [86]: round(3.5) Out[86]: 4.0

como yo hubiera esperado Sin embargo, ahora en v3.2.3 :

In [32]: round(2.5) Out[32]: 2 In [33]: round(3.5) Out[33]: 4

Esto parece contrario a la intuición y contrario a lo que entiendo acerca del redondeo (y está destinado a confundir a las personas). El inglés no es mi lengua materna, pero hasta que lo leí pensé que sabía lo que significaba redondear: - / Estoy seguro de que en el momento en que se presentó v3 debe haber habido una discusión sobre esto, pero no pude encontrar una buena razón para mi búsqueda

  1. ¿Alguien tiene una idea de por qué esto se cambió a esto?
  2. ¿Hay algún otro lenguaje de programación convencional (por ejemplo, C, C ++, Java, Perl, ...) que haga este tipo de redondeo (a mí inconsistente)?

¿Que me estoy perdiendo aqui?

ACTUALIZACIÓN: el comentario de @ Li-aungYip sobre "Redondeo al banco" me dio el término / palabras clave de búsqueda adecuados para buscar y encontré esta pregunta ASÍ: ¿Por qué .NET utiliza el redondeo bancario como valor predeterminado? , entonces leeré eso cuidadosamente.


La forma de Python 3.0 se considera el método estándar de redondeo en estos días, aunque algunas implementaciones de lenguaje aún no están en el bus.

La técnica simple "siempre redonda 0.5 arriba" da como resultado un ligero sesgo hacia el número más alto. Con un gran número de cálculos, esto puede ser significativo. El enfoque de Python 3.0 elimina este problema.

Hay más de un método de redondeo de uso común. IEEE 754, el estándar internacional para matemática de punto flotante, define cinco métodos de redondeo diferentes (el utilizado por Python 3.0 es el predeterminado). Y hay otros.

Este comportamiento no es tan conocido como debería ser. AppleScript fue, si no recuerdo mal, uno de los primeros en adoptar este método de redondeo. El comando round en AppleScript en realidad ofrece varias opciones, pero el redondeo hacia la igualdad es el predeterminado, como lo es en IEEE 754. Aparentemente, el ingeniero que implementó el comando round se hartó tanto con todas las solicitudes para "hacer que funcione como yo" aprendido en la escuela "que implementó precisamente eso: round 2.5 rounding as taught in school es un comando válido de AppleScript. :-)


Puede controlar el redondeo que obtiene en Py3000 utilizando el módulo Decimal :

>>> decimal.Decimal(''3.5'').quantize(decimal.Decimal(''1''), rounding=decimal.ROUND_HALF_UP) >>> Decimal(''4'') >>> decimal.Decimal(''2.5'').quantize(decimal.Decimal(''1''), rounding=decimal.ROUND_HALF_EVEN) >>> Decimal(''2'') >>> decimal.Decimal(''3.5'').quantize(decimal.Decimal(''1''), rounding=decimal.ROUND_HALF_DOWN) >>> Decimal(''3'')


Recientemente tuve problemas con esto, también. Por lo tanto, he desarrollado un módulo python 3 que tiene 2 funciones trueround () y trueround_precision () que abordan esto y dan el mismo comportamiento de redondeo cuando se utilizan desde la escuela primaria (no el redondeo bancario). Aquí está el módulo. Simplemente guarde el código y cópielo o impórtelo. Nota: el módulo trueround_precision puede cambiar el comportamiento de redondeo según las necesidades según los indicadores ROUND_CEILING, ROUND_DOWN, ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_UP y ROUND_05UP en el módulo decimal (consulte la documentación de los módulos para obtener más información). Para las siguientes funciones, consulte las cadenas de documentación o use help (trueround) y help (trueround_precision) si las copió en un intérprete para obtener más documentación.

#! /usr/bin/env python3 # -*- coding: utf-8 -*- def trueround(number, places=0): '''''' trueround(number, places) example: >>> trueround(2.55, 1) == 2.6 True uses standard functions with no import to give "normal" behavior to rounding so that trueround(2.5) == 3, trueround(3.5) == 4, trueround(4.5) == 5, etc. Use with caution, however. This still has the same problem with floating point math. The return object will be type int if places=0 or a float if places=>1. number is the floating point number needed rounding places is the number of decimal places to round to with ''0'' as the default which will actually return our interger. Otherwise, a floating point will be returned to the given decimal place. Note: Use trueround_precision() if true precision with floats is needed GPL 2.0 copywrite by Narnie Harshoe <[email protected]> '''''' place = 10**(places) rounded = (int(number*place + 0.5if number>=0 else -0.5))/place if rounded == int(rounded): rounded = int(rounded) return rounded def trueround_precision(number, places=0, rounding=None): '''''' trueround_precision(number, places, rounding=ROUND_HALF_UP) Uses true precision for floating numbers using the ''decimal'' module in python and assumes the module has already been imported before calling this function. The return object is of type Decimal. All rounding options are available from the decimal module including ROUND_CEILING, ROUND_DOWN, ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_UP, and ROUND_05UP. examples: >>> trueround(2.5, 0) == Decimal(''3'') True >>> trueround(2.5, 0, ROUND_DOWN) == Decimal(''2'') True number is a floating point number or a string type containing a number on on which to be acted. places is the number of decimal places to round to with ''0'' as the default. Note: if type float is passed as the first argument to the function, it will first be converted to a str type for correct rounding. GPL 2.0 copywrite by Narnie Harshoe <[email protected]> '''''' from decimal import Decimal as dec from decimal import ROUND_HALF_UP from decimal import ROUND_CEILING from decimal import ROUND_DOWN from decimal import ROUND_FLOOR from decimal import ROUND_HALF_DOWN from decimal import ROUND_HALF_EVEN from decimal import ROUND_UP from decimal import ROUND_05UP if type(number) == type(float()): number = str(number) if rounding == None: rounding = ROUND_HALF_UP place = ''1.'' for i in range(places): place = ''''.join([place, ''0'']) return dec(number).quantize(dec(place), rounding=rounding)

Espero que esto ayude,

Narnie


Solo para agregar aquí una nota importante de la documentación:

https://docs.python.org/dev/library/functions.html#round

Nota

El comportamiento de round () para flotadores puede ser sorprendente: por ejemplo, round (2.675, 2) da 2.67 en lugar de los 2.68 esperados. Esto no es un error: es el resultado del hecho de que la mayoría de las fracciones decimales no se pueden representar exactamente como un flotante. Consulte Aritmética de punto flotante: problemas y limitaciones para obtener más información.

Así que no se sorprenda de obtener los siguientes resultados en Python 3.2:

>>> round(0.25,1), round(0.35,1), round(0.45,1), round(0.55,1) (0.2, 0.3, 0.5, 0.6) >>> round(0.025,2), round(0.035,2), round(0.045,2), round(0.055,2) (0.03, 0.04, 0.04, 0.06)