Haskell et les quadratiques
-
11-07-2019 - |
Question
Je dois écrire un programme pour résoudre les problèmes de quadrature, renvoyant un résultat de nombre complexe.
J’ai eu jusqu’à présent à définir un nombre complexe, en déclarant qu’il faisait partie de num, afin que +, - et * - puissent avoir lieu.
J'ai également défini un type de données pour une équation du second degré, mais je suis maintenant bloqué dans la résolution du problème du second degré. Mes calculs sont plutôt médiocres, toute aide serait donc grandement appréciée ...
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) = STUCK!
EDIT: Il semble que je n’aie pas compris l’intérêt d’utiliser mon propre type de données à nombre complexe est d’en savoir plus sur les types de données personnalisés. Je suis bien conscient que je pourrais utiliser complex.data. Toute aide pouvant être apportée à l'aide de ma solution à ce jour serait grandement appréciée. \
MODIFIER 2: Il semble que ma question initiale ait été formulée de manière horrible. Je suis conscient que la formule quadratique me rendra les deux (ou la seule) racine. J'ai du mal à renvoyer ces racines sous forme de tuple (complexe) avec le code ci-dessus.
Je sais bien que je pourrais utiliser les fonctions quadratiques intégrées telles qu'elles ont été affichées ci-dessous, mais ce n'est pas l'exercice. L’idée derrière l’exercice et la création de son propre type de données de nombre complexe est d’apprendre sur les types de données personnalisés.
La solution
Comme dit newacct, il n’ya que l’équation du second degré:
(-b +- sqrt(b^2 - 4ac)) / 2a
module QuadraticSolver where
import Data.Complex
data Quadratic a = Quadratic a a a deriving (Show, Eq)
roots :: (RealFloat a) => Quadratic a -> [ Complex a ]
roots (Quadratic a b c) =
if discriminant == 0
then [ numer / denom ]
else [ (numer + root_discriminant) / denom,
(numer - root_discriminant) / denom ]
where discriminant = (b*b - 4*a*c)
root_discriminant = if (discriminant < 0)
then 0 :+ (sqrt $ -discriminant)
else (sqrt discriminant) :+ 0
denom = 2*a :+ 0
numer = (negate b) :+ 0
en pratique:
ghci> :l QuadraticSolver
Ok, modules loaded: QuadraticSolver.
ghci> roots (Quadratic 1 2 1)
[(-1.0) :+ 0.0]
ghci> roots (Quadratic 1 0 1)
[0.0 :+ 1.0,(-0.0) :+ (-1.0)]
Et en vous adaptant pour utiliser vos termes:
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)
Bien que je n'ai pas testé ce code
Autres conseils
Etant donné que le sqrt
de Haskell peut également gérer des nombres complexes, la solution de rampion peut encore être simplifiée:
import Data.Complex
-- roots for quadratic equations with complex coefficients
croots :: (RealFloat a) =>
(Complex a) -> (Complex a) -> (Complex a) -> [Complex a]
croots a b c
| disc == 0 = [solution (+)]
| otherwise = [solution (+), solution (-)]
where disc = b*b - 4*a*c
solution plmi = plmi (-b) (sqrt disc) / (2*a)
-- roots for quadratic equations with real coefficients
roots :: (RealFloat a) => a -> a -> a -> [Complex a]
roots a b c = croots (a :+ 0) (b :+ 0) (c :+ 0)
Vous pouvez également utiliser cette fonction croots
avec votre propre type de données, si vous modifiez les types pour les adapter à votre implémentation (et appelez votre fonction root
au lieu de sqrt
).