Erreur de virgule flottante Haskell
-
22-07-2019 - |
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)
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
.