3

Ich muss ein Programm schreiben, Quadrate zu lösen, ein komplexes Ergebnis zurückgeben.Haskell und Quadratics

Ich bin so weit gekommen, indem ich eine komplexe Zahl definiere und sie als Teil von num deklariere, damit +, - und * - ing stattfinden können.

Ich habe auch einen Datentyp für eine quadratische Gleichung definiert, aber ich bin jetzt mit der tatsächlichen Lösung der quadratischen fest. Meine Mathe ist ziemlich schlecht, so dass jede Hilfe sehr geschätzt ...

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 würde: Ich scheine den ganzen Punkt verpaßt zu haben, meinen eigenen komplexe Zahl Datentyp zu verwenden, ist über benutzerdefinierte Datentypen zu lernen. Ich bin mir bewusst, dass ich complex.data verwenden könnte. Jede Hilfe, die gegeben werden konnte meine-Lösung so weit würde sehr geschätzt \

EDIT 2:. Es scheint, dass meine erste Frage war schrecklich formuliert. Ich bin mir bewusst, dass die quadratische Formel mir (oder nur der einen) Wurzel zurückgibt. Wo ich Probleme habe, gebe ich diese Wurzeln als (komplexes, komplexes) Tupel mit dem obigen Code zurück.

Ich bin mir bewusst, dass ich die eingebauten quadratischen Funktionen wie unten angezeigt verwenden könnte, aber das ist nicht die Übung. Die Idee hinter der Übung und das Erstellen eines eigenen Datentyps mit komplexen Zahlen besteht darin, sich über benutzerdefinierte Datentypen zu informieren.

+3

können Sie 'Complex' von' Data.Complex' – yairchu

+0

ich könnte, aber wir wurden aufgefordert, unsere eigenen komplexen Datentypen zu definieren. Das Bit, mit dem ich Probleme habe, ist die Umwandlung der reellen Form quadratisches Polynom: a.x^2 + b.x + c in komplexe Zahlen. – Thomas

+0

ist es das gleiche. Sie haben alle notwendigen Operationen, verwenden Sie einfach die gleiche Formel. (-b +/- (sqrt (bb-4ac))/2a ... – nlucaroni

Antwort

6

Wie newacct sagte, es ist nur die quadratische Gleichung:

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

in der Praxis:

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)] 

und die Anpassung Ihrer Begriffe zu verwenden:

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) 

Obwohl ich habe diesen Code nicht getestet

+0

Es funktioniert, wenn es echte Wurzeln gibt, danke. "löse (Q 1 2 1)" erzeugt "(-1,0, -1,0)" und "löse (Q 1 2 0)" erzeugt "(0,0, -2,0)". Does't nicht nicht echte Wurzeln obwohl lösen. Ich werde jedoch eine separate Frage dazu stellen. "solve (Q 1 2 2)" verursacht diesen Fehler (Programmfehler: Musterübereinstimmungsfehler: v1618_v1655 (C -1. # IND -1. # IND) – Thomas

5

Seit Haskells sqrt können auch selbst sein können komplexe Zahlen, rampion Lösung Griff weiter vereinfacht:

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) 

Sie auch diese croots Funktion mit Ihrem eigenen Datentyp verwenden können, wenn Sie die Typen ändern Ihre Implementierung zu passen (und rufen Sie Ihre root Funktion anstelle von sqrt).