2017-09-18 2 views
-3

私は言いますが、数学は私の強い訴訟ではありません。私はData.Complexパッケージを使用してHow to find the cube root of a negative integer such that it does not return NaN?のためのまともな結果を得るために期待していたが、私はData.Complexパッケージは、-8 + 0i((-8):+ 0)の立方根に奇妙な結果をもたらします

*Main> ((-8):+0) ** (1/3) 
1.0 :+ 1.732050807568877 

ように私は-2は実部と0が虚部である(-2.0):+0のような何かを得るために期待さないとき。しかし、結果は重大な虚偽の部分で判明します。私は、Complexタイプのインスタンス(**)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 

だから我々は、通常Complexexplogインスタンスがどのように見えるexp (log x * y)部分を見ていなければなりません。

exp (x:+y)  = expx * cos y :+ expx * sin y 
        where expx = exp x 
log z   = log (magnitude z) :+ phase z 

次に、私は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 

私はスタックしています。私はちょうどsqrt (realPart z^2 + imagPart z^2)のようにします。

何が間違っていますか?あなたはそれを3乗で見ることができるよう

+5

複素数を扱うときにどのような根をとるかは重要な問題ではありません。あなたはおそらくプリンシパルルートを取得します。問題をよりよく理解するためにWikipediaをチェックしてください。彼らは実際に(-8)^(1/3)の例を持っています。 https://en.m.wikipedia.org/wiki/Nth_root – LudvigH

+0

...しかし、あなたの問題の迅速な解決策は、正の数の正規のライブラリの周りにラッパーを書くことです。負の数 – LudvigH

答えて

7

さて、あなたはを得た答えは、-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の3つの立方根があります。あなたが決定してきたように、((-8):+0)**(1/3)によって生成立方根が特定され

> 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] 
> 

> let j = (-1/2):+sqrt(3)/2 -- a cube root of 1 
> let units = [1,j,j*j]  -- that can generate them all 

と上記の値によってそれらを掛ける:あなたは1の3つの立方根を計算することにより、それらを計算することができます立方根-8によって計算:

> exp(log((-8):+0)*(1/3)) 
1.0 :+ 1.732050807568877 
> 

はその注目に値するであってもよい(1)にexplogの定義は、奇妙に見えるかもしれませんが、複素数の関数の標準的な数学的定義です。 (2)x ** yの定義が複素数の場合はexp(log(x)*y)となり、数学的には理にかなっており、((-8):+0)**(1/3)には-8を与えなければならないという性質を含め、期待するべきすべての特性が保証されています。(logの定義で使用)magnitudeの定義については

、あなたのシンプルな定義があまりにも動作します:

> magnitude (-8) 
8.0 
> sqrt (realPart (-8)^2 + imagPart (-8)^2) 
8.0 
> 

しかし、Data.Complexmagnitudeの定義が例で正しい答えを提供するために選択されています関係する数字が非常に大きい場合:

> magnitude 1e300 
1.0e300 
> sqrt (realPart 1e300^2 + imagPart 1e300^2) 
Infinity 
> 
関連する問題