2009-08-04 53 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`。 – 2012-02-16 13:48:16

回答

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,接着是“南”(非数字),拧一切

+0

为优秀的ASCII字根+1。 – 2009-08-04 16:33:53

1

关闭我的头顶:它可能是您为Complexshow定义的问题。

我注意到你没有默认情况下是这样的:

| otherwise = ... 

因此,如果有ri你的条件是不可穷尽的,你会得到一个pattern match failure

+0

拥抱似乎不喜欢关键字默认。无论如何,这不会是肯定的,因为展会综合体涵盖所有案例。 – Thomas 2009-08-04 10:56:44

+0

啊,对不起,SuperBloup是正确的,否则``是关键字。 我编辑了我的回复。 – dukedave 2009-08-04 13:28:23

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在告诉你哪里出了问题方面显然是胜利者。