es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿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?

Tags:  , , ,

Answer

  1. Avatar for 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:

    épsilon = 1e-6
    
    si 0 < abs(delta) <= 0.0001 + épsilon:
        ...
    elif 0.0001 + épsilon < abs(delta) <= 0.0002 + épsilon:
        ...
    elif 0.0002 + épsilon < abs(delta) <= 0.0003 + épsilon:
        ...
    elif abs(delta) > 0.0003 + épsilon:
        ...
    

    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ódulo decimal para redondear el valor decimal a un número específico de lugares decimales antes de aplicar el método label_change_price. Por ejemplo:

    dt["OPEN"] = dt["OPEN"].apply(lambda x: x.quantize(Decimal('.0000001')))
    dt["OPEN"] = dt["OPEN"].apply(label_change_price)
    

    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.

Comments are closed.