¿Cómo comparar float y decimal en Python?
Tengo una columna (decimal.Decimal
) en un dataframe como el siguiente:
dt = pd.DataFrame({"OPEN": [-0.00010,-0.0114, 0.0066,-0.0044,-0.0012,-0.0005,
0.0005,-0.0037, -0.0029, 0.0034, 0.0003, 0.0001 ]})
dt["OPEN"] = dt["OPEN"].apply(Decimal)
y me gustaría aplicar el siguiente método sobre la columna Open
:
def label_change_price(delta):
if 0 < abs(delta) < 0.0001:
print(" Valor de retorno: ",0, "Delta: ",delta)
return 0
elif 0.0001 <= abs(delta) < 0.0002:
print(" Valor de retorno: ",1, "Delta: ",delta)
return int(np.sign(delta)) * 1
elif 0.0002 <= abs(delta) < 0.0003:
print(" Valor de retorno: ",2, "Delta: ",delta)
return int(np.sign(delta)) * 2
elif 0.0003 <= abs(delta):
print(" Valor de retorno: ",3, "Delta: ",delta)
return int(np.sign(delta)) * 3
Cuando ejecuto el código, para la primera fila (-0.00010
) imprime:
Valor de retorno: 0 Delta: -0.00010
lo cual es incorrecto, ya que debería devolver 1
, sin embargo devuelve 0
.
En otras palabras, la primera condición en el if
se cumple y no continúa con el segundo elif
.
Entonces, ¿por qué mi segundo elif 0.0001 <= abs(delta) < 0.0002:
no está funcionando bien cuando delta es 0.0001? ¿Y cómo puedo solucionarlo?
davy.ai
El problema con la segunda condición
elif
que no se cumple cuando delta es exactamente 0.0001, se debe a errores de precisión de punto flotante. Al trabajar con valores decimales, es importante tener en cuenta que las representaciones de punto flotante no siempre son exactas debido a la forma en que se almacenan los números en memoria.Para solucionar este problema, una solución es definir un pequeño valor de épsilon (por ejemplo, 1e-6) y ajustar las condiciones en las instrucciones if-elif en consecuencia. Por ejemplo:
Al agregar un pequeño valor épsilon al límite superior de cada intervalo, permitimos cierta tolerancia en la precisión del valor decimal y aseguramos que se cumpla la condición correcta para valores cercanos pero no exactamente iguales a los límites del intervalo.
Otra solución es utilizar el método
quantize
incorporado en el módulodecimal
para redondear el valor decimal a un número específico de lugares decimales antes de aplicar el métodolabel_change_price
. Por ejemplo:Esto primero redondeará los valores decimales a 7 lugares decimales antes de aplicar el método
label_change_price
, lo que debería ayudar a evitar errores de precisión. Tenga en cuenta que el número de lugares decimales que elija redondear dependerá del nivel de precisión requerido para su aplicación.