Red*_*edu -3 haskell complex-numbers
我不得不说,数学不是我的强项.我希望得到一个不错的结果如何找到负整数的立方根,使其不返回NaN?通过使用Data.Complex包,但当我喜欢
*Main> ((-8):+0) ** (1/3)
1.0 :+ 1.732050807568877
Run Code Online (Sandbox Code Playgroud)
我希望能得到像(-2.0):+0-2是真实部分,0是虚部的东西.然而,结果显示出一个重要的想象部分.我检查了它所声明(**) RealFloat的Complex类型的实例;
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
Run Code Online (Sandbox Code Playgroud)
因此,我们必须正常地看看看起来像的exp (log x * y)地方exp和log实例Complex;
exp (x:+y) = expx * cos y :+ expx * sin y
where expx = exp x
log z = log (magnitude z) :+ phase z
Run Code Online (Sandbox Code Playgroud)
然后我继续前进到magnitude定义为;
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
Run Code Online (Sandbox Code Playgroud)
我被卡住了.我只是喜欢sqrt (realPart z ^ 2 + imagPart z ^ 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
>
Run Code Online (Sandbox Code Playgroud)
它不是你想要的立方根.
实际上,有三个立方根--8.您可以通过计算一个三个立方根来计算它们:
> let j = (-1/2):+sqrt(3)/2 -- a cube root of 1
> let units = [1,j,j*j] -- that can generate them all
Run Code Online (Sandbox Code Playgroud)
并将它们乘以上面的值:
> 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]
>
Run Code Online (Sandbox Code Playgroud)
正如您所确定的,生成的((-8):+0)**(1/3)立方根是-8的特定立方根,由下式计算:
> exp(log((-8):+0)*(1/3))
1.0 :+ 1.732050807568877
>
Run Code Online (Sandbox Code Playgroud)
这可能是值得指出的是,(1)的定义exp,并log在Data.Complex,虽然他们可能看起来很奇怪,是这些功能的复杂数字标准的数学定义; 和(2)的定义x ** y为exp(log(x)*y)复杂的数字使得数学上非常有意义,并确保x ** y有你应该期望的所有属性,包括体积测量属性((-8):+0)**(1/3)应该给你-8.
至于(在定义中magnitude使用)的定义log,你的简单定义也会起作用:
> magnitude (-8)
8.0
> sqrt (realPart (-8) ^ 2 + imagPart (-8) ^ 2)
8.0
>
Run Code Online (Sandbox Code Playgroud)
但是,在所涉及的数字非常大的情况下,选择magnitudein 的定义是Data.Complex为了提供正确的答案:
> magnitude 1e300
1.0e300
> sqrt (realPart 1e300 ^ 2 + imagPart 1e300 ^ 2)
Infinity
>
Run Code Online (Sandbox Code Playgroud)