Haskell e Quadráticas
-
11-07-2019 - |
Pergunta
Eu tenho que escrever um programa para resolver equações quadráticas, retornando um resultado número complexo.
Eu recebi até agora, com a definição de um número complexo, declarando que ele seja parte de num, então +, - e * -. Ção pode ocorrer
Eu também já definiu um tipo de dados para uma equação quadrática, mas im agora preso com a resolução real do quadrática. Minha matemática é bastante pobre, por isso qualquer ajuda seria muito apreciada ...
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: Eu pareço ter perdido toda a ponto de usar o meu próprio número complexo tipo de dados é aprender sobre tipos de dados personalizados. Estou bem ciente de que eu poderia usar complex.data. Qualquer ajuda que poderia ser dada usando minha solução até agora seria muito apreciada. \
EDIT 2: Parece que a minha pergunta inicial foi redigido horrivelmente. Estou ciente de que a fórmula quadrática retornará ambos (ou apenas um) de raiz para mim. Onde eu estou tendo problemas está retornando essas raízes como um (complexo complexo,) tupla com o código acima.
Estou bem ciente de que eu poderia usar o construída em função quadrática como foram apresentadas abaixo, mas este não é o exercício. A idéia por trás do exercício, e aqueles que criam seu complexo tipo de dados número, é aprender sobre os tipos de dados personalizado.
Solução
Como newacct disse, é apenas a equação quadrática:
(-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
na prática:
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)]
E se adaptar a usar seus termos:
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)
Embora eu não testei esse código
Outras dicas
Desde sqrt
de Haskell também pode lidar com números complexos, a solução da rampion pode até mesmo ser ainda mais simplificada:
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)
Você também pode usar esta função croots
com seu próprio tipo de dados, se você alterar os tipos para caber sua implementação (e chamar sua função root
vez de sqrt
).