2009-08-04 6 views
2

Итак, я закончил создание своего собственного сложного типа данных чисел в haskell.Ошибка с плавающей запятой 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) 
+0

Возможно, вы должны сделать свои поплавки строгими и, вероятно, двойными, то есть '! Double'. –

ответ

7

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

 
(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» (не число), завинчивания все остальное

+0

+1 для отличных радикалов ASCII. –

1

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

Я заметил, что вы не имеете дело по умолчанию, как это:

| otherwise = ... 

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

+0

Объятия не похоже на ключевое слово default. Во всяком случае, это не так уж точно, так как шоу-комплекс охватывает все случаи. – Thomas

+0

Ах, извините, SuperBloup был прав, 'иначе' является ключевым словом. Я отредактировал свой ответ. – dukedave

4

Дэйв ударил ноготь по голове.

С оригинальным кодом в GHCi, я получаю:

 
*Main> solve (Q 1 2 2) 
(*** Exception: c.hs:(11,4)-(17,63): Non-exhaustive patterns in function 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 - явный победитель, рассказывающий вам, что пошло не так.

+0

Я получаю все материалы NaN, но я не получаю никаких предупреждений. Кажется, что объятия не отображают какую-либо информацию. :( – Thomas

+1

Переключитесь на GHCi! Он отлично работает :) Вам все равно не нужны эти меню в Hugs, просто используйте команду ': l' для загрузки файла, который вы написали. Может потребоваться полный путь, если вы запустите GHCi из меню «Пуск». Кроме того, вы можете использовать GHC для компиляции в собственный исполняемый файл. –

 Смежные вопросы

  • Нет связанных вопросов^_^