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
- ¿Alguien tiene una idea de por qué esto se cambió a esto?
- ¿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)