3

Je dois écrire un programme pour résoudre des quadratiques, renvoyant un résultat numérique complexe. J'ai obtenu jusqu'ici, en définissant un nombre complexe, en le déclarant comme faisant partie de num, de sorte que +, - et * - puissent avoir lieu.Haskell et Quadratics

J'ai également défini un type de données pour une équation quadratique, mais je suis maintenant coincé avec la résolution réelle du quadratique. Mon calcul est assez pauvre, de sorte que toute aide serait 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 me semble avoir manqué le point entier d'utiliser mon propre numéro complexe type_données en savoir plus sur les types de données personnalisés. Je suis bien conscient que je pourrais utiliser complex.data. Toute aide qui pourrait être donnée à l'aide ma solution à ce jour serait grandement apprécié \

EDIT 2:. Il semble que ma question initiale était formulée horriblement. Je suis conscient que la formule quadratique me retournera les deux (ou seulement la racine). Là où j'ai de la difficulté à retourner ces racines sous la forme d'un tuple (complexe, complexe) avec le code ci-dessus. Je suis bien conscient que je pourrais utiliser les fonctions quadratiques intégrées comme cela a été montré 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 de se renseigner sur les types de données personnalisés.

+3

Je peux utiliser 'Complex' de' Data.Complex' – yairchu

+0

, mais on nous a demandé de définir nos propres types de données complexes. Le bit avec lequel je rencontre des problèmes est la conversion du polynôme quadratique sous forme réelle: a.x^2 + b.x + c en nombres complexes. – Thomas

+0

c'est pareil. vous avez toutes les opérations nécessaires, utilisez simplement la même formule. (-b +/- (sqrt (bb-4ac))/2a ... – nlucaroni

Répondre

6

Comme newacct dit, il est juste l'équation quadratique:

(-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 

dans la 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 l'adaptation à 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'a pas testé ce code

+0

Cela fonctionne quand il y a de vraies racines, merci. "solve (Q 1 2 1)" produit "(-1.0, -1.0)" et "solve (Q 1 2 0)" produit "(0.0, -2.0)". Ne résoudrez pas les racines non réelles cependant. Je vais cependant poster une question distincte à ce sujet. "solve (Q 1 2 2)" provoque cette erreur (Erreur de programme: échec de correspondance de modèle: v1618_v1655 (C -1. # IND -1. # IND) – Thomas

5

Depuis sqrt Haskell peut également gérer des nombres complexes, la solution de raiponce peut même être encore 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 changez les types en fonction de votre mise en œuvre (et appelez votre root au lieu de sqrt).