Pregunta

Así que he terminado de crear mi propio tipo de datos de números complejos en Haskell.

También, gracias a otra pregunta aquí, obtuve una función que resolverá una ecuación cuadrática.

El único problema ahora es que el código genera un error de análisis en los abrazos, cuando se intenta resolver una cuadrática con raíces complejas.

es decir En abrazos ...

Main> solve (Q 1 2 1)
(-1.0,-1.0)

Main> solve (Q 1 2 0)
(0.0,-2.0)

Main> solve (Q 1 2 2)
(
Program error: pattern match failure: v1618_v1655 (C -1.#IND -1.#IND)

Parece que es un problema después de que se haya aplicado la raíz cuadrada, pero realmente no estoy seguro. Cualquier ayuda para tratar de detectar lo que va mal o cualquier indicación sobre lo que significa este error sería brillante.

Gracias,

Thomas

El Código:

-- A complex number z = (re +im.i) is represented as a pair of Floats

data Complex = C {
re :: Float,
im :: Float
} deriving Eq

-- Display complex numbers in the normal way

instance Show Complex where
    show (C r i)
        | i == 0            = show r
        | r == 0            = show i++"i"
        | r < 0 && i < 0    = show r ++ " - "++ show (C 0 (i*(-1)))
        | r < 0 && i > 0    = show r ++ " + "++ show (C 0 i)
        | r > 0 && i < 0    = show r ++ " - "++ show (C 0 (i*(-1)))
        | r > 0 && i > 0    = show r ++ " + "++ show (C 0 i)


-- Define algebraic operations on complex numbers
instance Num Complex where
    fromInteger n       = C (fromInteger n) 0 -- tech reasons
    (C a b) + (C x y)   = C (a+x) (b+y)
    (C a b) * (C x y)   = C (a*x - b*y) (b*x + b*y)
    negate (C a b)      = C (-a) (-b)

instance Fractional Complex where
    fromRational r      = C (fromRational r) 0 -- tech reasons
    recip (C a b)       = C (a/((a^2)+(b^2))) (b/((a^2)+(b^2)))


root :: Complex -> Complex
root (C x y)
    | y == 0 && x == 0  = C 0 0
    | y == 0 && x > 0   = C (sqrt ( ( x + sqrt ( (x^2) + 0 ) ) / 2 ) )  0
    | otherwise         = C (sqrt ( ( x + sqrt ( (x^2) + (y^2) ) ) / 2 ) ) ((y/(2*(sqrt ( ( x + sqrt ( (x^2) + (y^2) ) ) / 2 ) ) ) ) )


-- quadratic polynomial : a.x^2 + b.x + c
data Quad = Q {
    aCoeff, bCoeff, cCoeff :: Complex
} deriving Eq


instance Show Quad where
    show (Q a b c) = show a ++ "x^2 + " ++ show b ++ "x + " ++ show c

solve :: Quad -> (Complex, Complex)
solve (Q a b c) = ( sol (+), sol (-) )
  where sol op = (op (negate b) $ root $ b*b - 4*a*c) / (2 * a)
¿Fue útil?

Solución

Sus números parecen desnormalizados en su error:

(C -1.#IND -1.#IND)

En este caso, no puede asumir que cualquier comparación en flotante ya no sea válida. Esto está en la definición de números de coma flotante. Entonces tu definición de espectáculo

show (C r i)
    | i == 0                        = show r
    | r == 0                        = show i++"i"
    | r < 0 && i < 0        = show r ++ " - "++ show (C 0 (i*(-1)))
    | r < 0 && i > 0        = show r ++ " + "++ show (C 0 i)
    | r > 0 && i < 0        = show r ++ " - "++ show (C 0 (i*(-1)))
    | r > 0 && i > 0        = show r ++ " + "++ show (C 0 i)

deja la oportunidad para una falla de patrón, debido a números desnormalizados. Puede agregar la siguiente condición

    | otherwise = show r ++ "i" ++ show i"

Ahora, por qué es así, cuando evalúas

b * b - 4 * a * c

con Q 1 2 2, obtienes -4, y luego en la raíz, caes en tu último caso, y en la segunda ecuación:

              y
-----------------------------
            ________________
           /        _______
          /        / 2    2
         /   x + \/ x  + y
 2 * \  /   ----------------
      \/           2

-4 + sqrt ((-4) ^ 2) == 0 , a partir de ahí, estás condenado, división por 0, seguido de un " NaN " (no un número), atornillando todo lo demás

Otros consejos

Dave golpeó el clavo en la cabeza.

Con el código original en GHCi, obtengo:

*Main> solve (Q 1 2 2)
(*** Exception: c.hs:(11,4)-(17,63): Non-exhaustive patterns in function show

Si actualizamos el bloque show:

instance Show Complex where
    show (C r i)
        | i == 0                        = show r
        | r == 0                        = show i++"i"
        | r < 0 && i < 0        = show r ++ " - "++ show (C 0 (i*(-1)))
        | r < 0 && i > 0        = show r ++ " + "++ show (C 0 i)
        | r > 0 && i < 0        = show r ++ " - "++ show (C 0 (i*(-1)))
        | r > 0 && i > 0        = show r ++ " + "++ show (C 0 i)
        | otherwise             = "???(" ++ show r ++ " " ++ show i ++ ")"

entonces obtenemos esta información en GHCi:

*Main> :l c.hs
[1 of 1] Compiling Main             ( c.hs, interpreted )

c.hs:22:0:
    Warning: No explicit method nor default method for `abs'
    In the instance declaration for `Num Complex'

c.hs:22:0:
    Warning: No explicit method nor default method for `signum'
    In the instance declaration for `Num Complex'
Ok, modules loaded: Main.
*Main> solve (Q 1 2 2)
(???(NaN NaN),???(NaN NaN))

Yo nací y crecí en GHCi, así que no sé exactamente cómo se compara Hugs en términos de advertencias y errores; pero parece que GHCi es un claro ganador al decirle qué salió mal.

Fuera de mi cabeza: Podría ser un problema con su definición de show para Complex .

Noto que no tiene un caso predeterminado como este:

 | otherwise = ...

Por lo tanto, si sus condiciones con r y i no son exhaustivas, obtendrá una falla de coincidencia de patrón .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top