1である必要があります(-1,1.2)
-
27-10-2019 - |
質問
GCCとGSLでMath.hを使用しています。これを評価する方法を考えていましたか?
私は、POW機能がPow(-1,1.2)を(-1)^6)^(1/5)として認識することを望んでいました。しかし、そうではありません。
これらを認識するC ++ライブラリを知っている人はいますか?おそらく、誰かが共有できる分解ルーチンを持っているでしょう。
解決
あなたが探しているようです pow(abs(x), y)
.
説明:あなたはその観点から考えているようです
バツy =(xn)(y/n)
そのn === 2を選択した場合、あなたは持っています
(バツ2)y/2 =((x2)1/2)y
しかし
(バツ2)1/2 = | x |
代替品が与えられます
| x |y
上記の操作は非陰性Xに対してのみ機能するため、これはストレッチですが、あなたはその仮定を使用することを選んだ人です。
他のヒント
数学的に、 pow(-1, 1.2)
単に定義されていません。負の数の分数指数を持つ力はありません。そして、そのような表現に対して単に何らかのアービトレイ価値を返すライブラリがないことを願っています。あなたもようなものを期待しますか
pow(-1, 0.5) = ((-1)^2)^(1/4) = 1
明らかに望ましくありません。
さらに、浮動小数点数 1.2
とはまったく同じではありません 6/5
. 。に最も近い二重精度数 1.2
は
1.1999999999999999555910790149937383830547332763671875
これを考えると、あなたは今どのような結果を期待しますか pow(-1, 1.2)
?
あなたが力に負の数を上げたい場合、特に分数の力 - を使用してください cpow()
方法。含める必要があります <complex>
それを使用する。
複雑な力を実行したいように聞こえます(cpow()
)そして、大きさを取ります(abs()
)その後。
>>> abs(cmath.exp(1.2*cmath.log(-1)))
1.0
>>> abs(cmath.exp(1.2*cmath.log(-293.2834)))
913.57662451612202
pow(a,b)
しばしば考えられ、として定義され、として実装されています exp(log(a)*b)
どこ log(a)
Aの自然対数です。 log(a)は、実数でa <= 0の場合は定義されていません。したがって、ネガティブAおよび整数の特別なケースを使用して関数を書く必要があります b
および/または b=1/(some_integer)
. 。整数用の特別ケースは簡単です b
, 、しかし b=1/(some_integer)
Sven Marnachが指摘したように、それは丸めの問題になりやすいです。
たぶんあなたのドメインのために pow(-a,b)
常にあるべきです -pow(a,b)
?しかし、その後、あなたはそのような関数を実装するだけなので、質問がより多くの説明を必要とすると思います。
Duskwuffが提案したように、はるかに堅牢で「数学的」解決策は、複雑な関数ログとExpを使用することですが、表面よりもはるかに「複雑」(私のしゃれを許します)です(あっても、私のしゃれを言い訳) cpow
関数)。そして、多くのPOW()を計算する必要がある場合、それははるかに遅くなります。
これで、問題のドメインに関連する場合と関連性がある場合がある複雑な数字で重要なキャッチがあります。正しく行われた場合、 pow(a,b)
1つではなく、しばしばです いくつかの複雑な数字, 、しかし、あなたが気にする場合は、そのうちの1つは、コードで単純に無視したり、計算したりすることができるほぼゼロの想像上の部分(ラウンドオフエラーのためにゼロではないでしょう)の複雑な数になります。
それを示すために、何を考えてください pow(-1,.5)
は。それは数字です X
そのような X^2==-1
. 。何だと思う?そのような数字は2つあります。 i
と -i
. 。一般的、 pow(-1, 1/N)
正確に持っています N
ソリューションは、そのうちの1つだけに興味がありますが。
のすべての結果の想像上の部分の場合 pow(a,b)
重要であり、それはあなたが間違った値を渡していることを意味します。記述する範囲内の単一精度の浮動小数点値の場合、1E-6*max(abs(a)、abs(b))は、「十分に重要な」しきい値を定義するための良い出発点です。極端な「間違った値」はそうでしょう pow(-1,0.5)
それが戻ってきます 0 + 1i
(0
実際には、 1
想像上の部分)。ここでは、想像上の部分は入力と実際の部分に比べて巨大であるため、入力値を台無しにしたことがわかります。
の合理的なシングルリターンと結果の実装で cpow()
, cpow(-1,0.3333)
おそらく次のようなものを返します -1+0.000001i
そして、重要な想像上の部分を持つ他の2つの値を無視します。だからあなたはその本当の価値を取ることができ、それがあなたの答えです。
使用する std::complex
. 。それがなければ、団結のルーツはあまり意味がありません。それで彼らは非常に理にかなっています。