lenguaje - python wikipedia
Redondea el número al entero más cercano (10)
He estado tratando de redondear números flotantes largos como:
32.268907563;
32.268907563;
31.2396694215;
33.6206896552;
...
Sin éxito hasta ahora.
math.ceil(x)
,
math.floor(x)
(aunque eso se redondearía hacia arriba o hacia abajo, que no es lo que estoy buscando) y
round(x)
que tampoco funcionó (todavía números flotantes) .
¿Qué puedo hacer?
EDITAR: CÓDIGO:
for i in widthRange:
for j in heightRange:
r, g, b = rgb_im.getpixel((i, j))
h, s, v = colorsys.rgb_to_hsv(r/255.0, g/255.0, b/255.0)
h = h * 360
int(round(h))
print(h)
¿No solo Python está haciendo la mitad de la mitad para igualar , según lo prescrito por IEEE 754 ?
Tenga cuidado al redefinir, o al usar el redondeo "no estándar" ...
(Ver también https://.com/a/33019948/109839 )
Para aspectos positivos, intente
int(x + 0.5)
Para que funcione también para los negativos, intente
int(x + (0.5 if x > 0 else -0.5))
int()
funciona como una función de piso y, por lo tanto, puede explotar esta propiedad.
Esta es definitivamente la forma más rápida.
Para este propósito, sugeriría hacer lo siguiente:
int(round(x))
Esto te dará el entero más cercano.
¡¡Espero que esto ayude!!
Si necesita (por ejemplo) una aproximación de dos dígitos para A, entonces
int(A*100+0.5)/100.0
hará lo que está buscando.
Si necesita una aproximación de tres dígitos, multiplique y divida por 1000 y así sucesivamente.
Su solución es llamar sin especificar el segundo argumento (número de decimales)
>>> round(0.44)
0
>>> round(0.64)
1
que es un resultado mucho mejor que
>>> int(round(0.44, 2))
0
>>> int(round(0.64, 2))
0
De la documentación de Python en https://docs.python.org/3/library/functions.html#round
ronda (número [, ndigits])
Número de retorno redondeado a ndigits de precisión después del punto decimal. Si se omite ndigits o es None, devuelve el entero más cercano a su entrada.
Nota
El comportamiento de round () para flotadores puede ser sorprendente: por ejemplo, round (2.675, 2) da 2.67 en lugar del esperado 2.68. 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 coma flotante: problemas y limitaciones para obtener más información.
También puede usar numpy asumiendo si está usando python3.x aquí hay un ejemplo
import numpy as np
x = 2.3
print(np.rint(x))
>>> 2.0
Use
round(x, y)
.
Redondeará su número hasta el lugar decimal deseado.
Por ejemplo:
>>> round(32.268907563, 3)
32.269
Utilizo y puedo recomendar la siguiente solución (python3.6):
y = int(x + (x % (1 if x >= 0 else -1)))
Funciona bien para números medios (positivos y negativos) y funciona incluso más rápido que int (round (x)):
round_methods = [lambda x: int(round(x)),
lambda x: int(x + (x % (1 if x >= 0 else -1))),
lambda x: np.rint(x).astype(int),
lambda x: int(proper_round(x))]
for rm in round_methods:
%timeit rm(112.5)
Out:
201 ns ± 3.96 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
159 ns ± 0.646 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
925 ns ± 7.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
1.18 µs ± 8.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
for rm in round_methods:
print(rm(112.4), rm(112.5), rm(112.6))
print(rm(-12.4), rm(-12.5), rm(-12.6))
print(''='' * 11)
Out:
112 112 113
-12 -12 -13
===========
112 113 113
-12 -13 -13
===========
112 112 113
-12 -12 -13
===========
112 113 113
-12 -13 -13
===========
round(value,significantDigit)
es la solución ordinaria, sin embargo, esto no funciona como cabría esperar desde una perspectiva matemática cuando los valores de round terminan en
5
.
Si el
5
está en el dígito justo después del redondeado, estos valores solo se redondean a veces como se esperaba (es decir,
8.005
redondeando a dos dígitos decimales da
8.01
).
Para ciertos valores debido a las peculiaridades de las matemáticas de coma flotante, ¡se redondean hacia abajo en su lugar!
es decir
>>> round(1.0005,3)
1.0
>>> round(2.0005,3)
2.001
>>> round(3.0005,3)
3.001
>>> round(4.0005,3)
4.0
>>> round(1.005,2)
1.0
>>> round(5.005,2)
5.0
>>> round(6.005,2)
6.0
>>> round(7.005,2)
7.0
>>> round(3.005,2)
3.0
>>> round(8.005,2)
8.01
Extraño.
Suponiendo que su intención es hacer el redondeo tradicional para las estadísticas en las ciencias, este es un útil contenedor para que la función de
round
funcione como se esperaba y necesita
import
cosas adicionales como
Decimal
.
>>> round(0.075,2)
0.07
>>> round(0.075+10**(-2*5),2)
0.08
¡Ajá! Entonces, en base a esto, podemos hacer una función ...
def roundTraditional(val,digits):
return round(val+10**(-len(str(val))-1), digits)
Básicamente, esto agrega un valor garantizado para ser más pequeño que el dígito menos dado de la cadena que está tratando de usar.
Al agregar esa pequeña cantidad, preserva el comportamiento de la
round
en la mayoría de los casos, mientras que ahora se asegura que si el dígito inferior al que se está redondeando es
5
se redondea hacia arriba, y si es
4
se redondea hacia abajo.
El enfoque de usar
10**(-len(val)-1)
fue deliberado, ya que es el número pequeño más grande que puede agregar para forzar el cambio, al tiempo que garantiza que el valor que agregue nunca cambie el redondeo, incluso si el decimal
.
Está perdido.
Podría usar solo
10**(-len(val))
con un
if (val>1)
para restar
1
más ... pero es más simple restar siempre el
1
ya que eso no cambiará mucho el rango aplicable de números decimales que esta solución puede manejar adecuadamente.
Este enfoque fallará si sus valores alcanzan los límites del tipo, fallará, pero para casi todo el rango de valores decimales válidos debería funcionar.
También puede usar la biblioteca decimal para lograr esto, pero el contenedor que propongo es más simple y puede preferirse en algunos casos.
Editar:
Gracias
Blckknght
por señalar que el caso de
5
franjas ocurre solo para ciertos valores.
Además, una versión anterior de esta respuesta no fue lo suficientemente explícita como para que el comportamiento de redondeo impar
ocurra solo cuando el dígito inmediatamente inferior al dígito al que está redondeando tiene un
5
.
int(round(x))
Lo redondeará y lo cambiará a entero
EDITAR:
No está asignando int (round (h)) a ninguna variable. Cuando llama a int (round (h)), devuelve el número entero pero no hace nada más; tienes que cambiar esa línea por:
h = int(round(h))
Para asignar el nuevo valor a h
EDITAR 2:
Como dijo @plowman en los comentarios, la
round()
Python no funciona como uno esperaría normalmente, y eso se debe a que la forma en que se almacena el número como variable generalmente no es la forma en que se ve en la pantalla.
Hay muchas respuestas que explican este comportamiento:
round () en Python no parece estar redondeando correctamente
Una forma de evitar este problema es usar el decimal como se indica en esta respuesta: https://.com/a/15398691/4345659
Para que esta respuesta funcione correctamente sin usar bibliotecas adicionales, sería conveniente usar una función de redondeo personalizada.
Después de muchas correcciones, se me ocurrió la siguiente solución, que hasta donde probé evitaba todos los problemas de almacenamiento.
Se basa en el uso de la representación de cadena, obtenida con
repr()
(¡NO
str()
!).
Parece hacky pero fue la única forma que encontré para resolver todos los casos.
Funciona con Python2 y Python3.
def proper_round(num, dec=0):
num = str(num)[:str(num).index(''.'')+dec+2]
if num[-1]>=''5'':
return float(num[:-2-(not dec)]+str(int(num[-2-(not dec)])+1))
return float(num[:-1])
Pruebas:
>>> print(proper_round(1.0005,3))
1.001
>>> print(proper_round(2.0005,3))
2.001
>>> print(proper_round(3.0005,3))
3.001
>>> print(proper_round(4.0005,3))
4.001
>>> print(proper_round(5.0005,3))
5.001
>>> print(proper_round(1.005,2))
1.01
>>> print(proper_round(2.005,2))
2.01
>>> print(proper_round(3.005,2))
3.01
>>> print(proper_round(4.005,2))
4.01
>>> print(proper_round(5.005,2))
5.01
>>> print(proper_round(1.05,1))
1.1
>>> print(proper_round(2.05,1))
2.1
>>> print(proper_round(3.05,1))
3.1
>>> print(proper_round(4.05,1))
4.1
>>> print(proper_round(5.05,1))
5.1
>>> print(proper_round(1.5))
2.0
>>> print(proper_round(2.5))
3.0
>>> print(proper_round(3.5))
4.0
>>> print(proper_round(4.5))
5.0
>>> print(proper_round(5.5))
6.0
>>>
>>> print(proper_round(1.000499999999,3))
1.0
>>> print(proper_round(2.000499999999,3))
2.0
>>> print(proper_round(3.000499999999,3))
3.0
>>> print(proper_round(4.000499999999,3))
4.0
>>> print(proper_round(5.000499999999,3))
5.0
>>> print(proper_round(1.00499999999,2))
1.0
>>> print(proper_round(2.00499999999,2))
2.0
>>> print(proper_round(3.00499999999,2))
3.0
>>> print(proper_round(4.00499999999,2))
4.0
>>> print(proper_round(5.00499999999,2))
5.0
>>> print(proper_round(1.0499999999,1))
1.0
>>> print(proper_round(2.0499999999,1))
2.0
>>> print(proper_round(3.0499999999,1))
3.0
>>> print(proper_round(4.0499999999,1))
4.0
>>> print(proper_round(5.0499999999,1))
5.0
>>> print(proper_round(1.499999999))
1.0
>>> print(proper_round(2.499999999))
2.0
>>> print(proper_round(3.499999999))
3.0
>>> print(proper_round(4.499999999))
4.0
>>> print(proper_round(5.499999999))
5.0
Finalmente, la respuesta corregida sería:
# Having proper_round defined as previously stated
h = int(proper_round(h))
EDITAR 3:
Pruebas:
>>> proper_round(6.39764125, 2)
6.31 # should be 6.4
>>> proper_round(6.9764125, 1)
6.1 # should be 7
El problema aquí es que el decimo decimal puede ser 9 y si
dec+1
-th dígito> = 5, el 9 se convertirá en 0 y un 1 debería llevarse al
dec-1
-th dígito.
Si tomamos esto en consideración, obtenemos:
def proper_round(num, dec=0):
num = str(num)[:str(num).index(''.'')+dec+2]
if num[-1]>=''5'':
a = num[:-2-(not dec)] # integer part
b = int(num[-2-(not dec)])+1 # decimal part
return float(a)+b**(-dec+1) if a and b == 10 else float(a+str(b))
return float(num[:-1])
En la situación descrita anteriormente,
b = 10
y la versión anterior concatenaría
a
y
b
lo que resultaría en una concatenación de
10
donde el 0 final desaparecería.
Esta versión transforma
b
al lugar decimal correcto basado en
dec
, como un acarreo adecuado.