Вопрос

Итак, я закончил создание собственного типа данных комплексного числа в Haskell.

Я также, благодаря другому вопросу здесь, получил функцию, которая решит квадратное уравнение.

Единственная проблема сейчас заключается в том, что код генерирует ошибку синтаксического анализа в объятиях при попытке решить квадратное уравнение со сложными корнями.

то естьВ объятиях...

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)

Мне кажется, что это проблема после применения квадратного корня, но я действительно не уверен.Любая помощь в попытке понять, что происходит не так, или какие-либо указания на то, что означает эта ошибка, была бы блестящей.

Спасибо,

Томас

Код:

-- 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)
Это было полезно?

Решение

Ваши числа кажутся денормализованными из-за вашей ошибки:

(C -1.#IND -1.#IND)

В этом случае вы не можете предполагать, что любое сравнение с плавающей запятой больше допустимо.Это определение чисел с плавающей запятой.Тогда ваше определение шоу

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 ++ "i" ++ show i"

Теперь о том, почему это так, когда вы оцениваете

b * b - 4 * a * c

с Q 1 2 2 вы получаете -4, а затем в корне вы попадаете в ваш последний случай и во второе уравнение:

              y
-----------------------------
            ________________
           /        _______
          /        / 2    2
         /   x + \/ x  + y
 2 * \  /   ----------------
      \/           2

-4 + sqrt( (-4) ^2) == 0, отсюда вы обречены, деление на 0, за которым следует «NaN» (не число), к черту все остальное

Другие советы

Дэйв попал в самую точку.

Используя исходный код в GHCi, я получаю:

*Main> solve (Q 1 2 2)
(*** Exception: c.hs:(11,4)-(17,63): Non-exhaustive patterns in function show

Если мы обновим блок 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 ++ ")"

тогда мы получим эту информацию в 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))

Я «родился и вырос» на GHCi, поэтому не знаю точно, с чем Hugs сравнивается по многословности предупреждений и ошибок;но похоже, что GHCi явно выигрывает, рассказывая вам, что пошло не так.

С верхней части моей головы:Это может быть проблема с вашим определением show для Complex.

Я заметил, что у вас нет такого случая по умолчанию:

 | otherwise = ...

Поэтому, если ваши условия с r и i не являются исчерпывающими, вы получите pattern match failure.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top