2

所以我已经完成了在 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)
4

3 回答 3

7

您的数字在您的错误中似乎非规范化:

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

在这种情况下,您不能假设任何对 float 的比较都有效。这是在浮点数的定义中。那么你对表演的定义

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”(不是数字),把其他所有东西都搞砸了

于 2009-08-04T10:55:11.090 回答
4

戴夫一针见血。

使用 GHCi 中的原始代码,我得到:

*主要>解决(Q 1 2 2)
(*** 例外:c.hs:(11,4)-(17,63):函数显示中的非详尽模式

如果我们更新显示块:

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 中得到这些信息:

*主> :l c.hs
[1 of 1] 编译 Main(c.hs,解释)

c.hs:22:0:
    警告:“abs”没有显式方法或默认方法
    在“Num Complex”的实例声明中

c.hs:22:0:
    警告:“signum”没有显式方法或默认方法
    在“Num Complex”的实例声明中
好的,已加载模块:主要。
*主要>解决(Q 1 2 2)
(???(NaN NaN),???(NaN NaN))

我是在 GHCi 上“出生和长大”的,所以我不知道 Hugs 在警告和错误的详细程度方面如何比较;但看起来 GHCi 在告诉你出了什么问题方面是一个明显的赢家。

于 2009-08-04T10:57:19.887 回答
1

在我脑海中浮现:你的showfor定义可能有问题Complex

我注意到您没有这样的默认情况:

 | otherwise = ...

因此,如果您的条件ri不是详尽无遗的,您将获得pattern match failure.

于 2009-08-04T10:24:51.260 回答