Question

J'ai donc fini de créer mon propre type de données de nombres complexes dans haskell.

J'ai également, grâce à une autre question ici, une fonction qui résoudra une équation du second degré.

Le seul problème, c’est que le code génère une erreur d’analyse dans les câlins lorsqu’on essaie de résoudre un problème quadratique avec des racines complexes.

i.e. Dans les câlins ...

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)

Cela me semble être un problème après l’application de la racine carrée, mais je ne suis vraiment pas sûr. Toute aide pour tenter de comprendre ce qui ne va pas ou toute indication quant à la signification de cette erreur serait géniale.

Merci,

Thomas

Le code:

-- 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)
Était-ce utile?

La solution

Vos chiffres semblent dénormalisés dans votre erreur:

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

Dans ce cas, vous ne pouvez plus présumer que toute comparaison sur float est valide. Ceci est dans la définition des nombres à virgule flottante. Ensuite, votre définition du spectacle

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)

laisse une possibilité d’échec de modèle en raison de nombres dénormalisés. Vous pouvez ajouter la condition suivante

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

Maintenant, pourquoi est-ce comme ça, quand vous évaluez

b * b - 4 * a * c

avec Q 1 2 2, vous obtenez -4, puis en racine, vous tombez dans votre dernier cas, et dans la deuxième équation:

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

-4 + sqrt ((-4) ^ 2) == 0 , à partir de là, vous êtes condamné, division par 0, suivi de la mention "NaN". (pas un nombre), en vissant tout le reste

Autres conseils

Dave a mis le doigt sur le clou.

Avec le code d'origine dans GHCi, je reçois:

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

Si nous mettons à jour le bloc 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 ++ ")"

alors nous obtenons cette information dans 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))

Je suis "né et j'ai grandi" sur GHCi, donc je ne sais pas exactement comment Hugs se compare en termes de verbosité des avertissements et des erreurs; mais on dirait que GHCi est clairement gagnant pour vous dire ce qui ne va pas.

De mémoire: cela pourrait être un problème avec votre définition de show pour Complex .

Je remarque que vous n'avez pas de cas par défaut comme celui-ci:

 | otherwise = ...

Par conséquent, si vos conditions avec r et i ne sont pas exhaustives, vous obtiendrez un échec de correspondance de modèle .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top