Haskell 对于-8+;0i(-8):&x2B;0

Haskell 对于-8+;0i(-8):&x2B;0,haskell,complex-numbers,Haskell,Complex Numbers,我不得不说,数学不是我的强项。我希望通过使用这个软件包可以得到一个不错的结果,但是当我喜欢的时候 *Main> ((-8):+0) ** (1/3) 1.0 :+ 1.732050807568877 我期望得到一些类似于(-2.0):+0的东西,其中-2是实部,0是虚部。然而,结果是一个重要的虚部。我已经检查了(**)RealFloat复杂类型的实例,它在其中声明: x ** y = case (x,y) of (_ , (0:+0)) -> 1 :+ 0 ((0:+0)

我不得不说,数学不是我的强项。我希望通过使用这个软件包可以得到一个不错的结果,但是当我喜欢的时候

*Main> ((-8):+0) ** (1/3)
1.0 :+ 1.732050807568877
我期望得到一些类似于
(-2.0):+0
的东西,其中-2是实部,0是虚部。然而,结果是一个重要的虚部。我已经检查了
(**)
RealFloat
复杂类型的
实例,它在其中声明:

x ** y = case (x,y) of
  (_ , (0:+0))  -> 1 :+ 0
  ((0:+0), (exp_re:+_)) -> case compare exp_re 0 of
             GT -> 0 :+ 0
             LT -> inf :+ 0
             EQ -> nan :+ nan
  ((re:+im), (exp_re:+_))
    | (isInfinite re || isInfinite im) -> case compare exp_re 0 of
             GT -> inf :+ 0
             LT -> 0 :+ 0
             EQ -> nan :+ nan
    | otherwise -> exp (log x * y)
  where
    inf = 1/0
    nan = 0/0
因此,我们必须正常地查看
exp(logx*y)
部分,其中
exp
log
复杂的
实例如下所示

exp (x:+y)     =  expx * cos y :+ expx * sin y
                  where expx = exp x
log z          =  log (magnitude z) :+ phase z
然后我转到
量级
,定义如下

magnitude :: (RealFloat a) => Complex a -> a
magnitude (x:+y) =  scaleFloat k
                     (sqrt (sqr (scaleFloat mk x) + sqr (scaleFloat mk y)))
                    where k  = max (exponent x) (exponent y)
                          mk = - k
                          sqr z = z * z
我被困的地方。我只想做
sqrt(realpartz^2+imagpartz^2)

我做错了什么?

好吧,你得到的答案是-8的立方根,你可以通过立方体看到:

> let x = ((-8):+0)**(1/3)
> x
1.0 :+ 1.732050807568877
> x^3
(-7.9999999999999964) :+ 2.220446049250313e-15
> x*x*x
(-7.9999999999999964) :+ 2.220446049250313e-15
> 
它不是你要找的立方根

事实上,有三个-8的立方根。可以通过计算其中一个的三个立方根来计算它们:

> let j = (-1/2):+sqrt(3)/2   -- a cube root of 1
> let units = [1,j,j*j]       -- that can generate them all
将它们乘以上面的值:

> map (*x) units  -- the cube roots of -8
[1.0 :+ 1.732050807568877,
 (-1.9999999999999996) :+ 1.1102230246251565e-16,
 0.9999999999999997 :+ (-1.7320508075688767)]
> map (^3) $ map (*x) units  -- prove they cube to -8
[(-7.9999999999999964) :+ 2.220446049250313e-15,
 (-7.999999999999995) :+ 1.3322676295501873e-15,
 (-7.999999999999992) :+ 8.881784197001252e-16]
>
正如您所确定的,
(-8):+0)**(1/3)
生成的立方根是-8的特定立方根,其计算公式为:

> exp(log((-8):+0)*(1/3))
1.0 :+ 1.732050807568877
> 
可能值得注意的是:(1)数据中
exp
log
的定义。复数
虽然看起来很奇怪,但却是这些复数函数的标准数学定义;(2)复数的
x**y
定义为
exp(log(x)*y)
,在数学上具有完美的意义,并确保
x**y
具有您应该期望的所有属性,包括cubing
(-8):+0)**(1/3)
应该给您-8的属性

至于
幅值的定义(用于
log
的定义),您更简单的定义也适用:

> magnitude (-8)
8.0
> sqrt (realPart (-8) ^ 2 + imagPart (-8) ^ 2)
8.0
>
但是,选择了
Data.Complex
中的
震级定义,以便在涉及的数字非常大的情况下提供正确答案:

> magnitude 1e300
1.0e300
> sqrt (realPart 1e300 ^ 2 + imagPart 1e300 ^ 2)
Infinity
> 

在处理复数时选择根并不是一件小事。你可能得到了主根。查看维基百科以更好地理解这件事。他们有一个例子(-8)^(1/3)实际上。。。但问题的快速解决方案是在正数的正常库周围编写一个包装器,并检查是否取负数的奇数根