私はGCCとGSLでmath.hを使用しています。これを評価する方法を考えていましたか?
pow関数がpow(-1,1.2)を((-1)^ 6)^(1/5)として認識することを期待していました。しかし、そうではありません。
これらを認識するC++ライブラリを知っている人はいますか?おそらく誰かが共有できる分解ルーチンを持っています。
私はGCCとGSLでmath.hを使用しています。これを評価する方法を考えていましたか?
pow関数がpow(-1,1.2)を((-1)^ 6)^(1/5)として認識することを期待していました。しかし、そうではありません。
これらを認識するC++ライブラリを知っている人はいますか?おそらく誰かが共有できる分解ルーチンを持っています。
数学的に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>
。
探しているようですpow(abs(x), y)
。
説明:あなたは次の観点から考えているようです
x y =(x N)(y / N)
N === 2を選択すると、次のようになります。
(x 2)y / 2 =((x 2)1/2)y
だが
(x 2)1/2 = | x |
代用すると
| x | y
上記の操作は負でないxに対してのみ機能するため、これは一筋縄ではいきませんが、その仮定を使用することを選択したのはあなたです。
複雑なパワー(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)
は、aの自然対数であるexp(log(a)*b)
と考えられ、定義され、実装されることがよくあります。log(a)
log(a)は、実数のa<=0に対して定義されていません。b
したがって、負のaと整数および/またはの特殊なケースで関数を作成する必要がありますb=1/(some_integer)
。整数の特殊なケースは簡単ですb
がb=1/(some_integer)
、Sven Marnachが指摘したように、丸めの問題が発生しやすいためです。
たぶんあなたのドメインpow(-a,b)
は常にあるべき-pow(a,b)
ですか?しかし、その場合はそのような関数を実装するだけなので、この質問にはさらに説明が必要だと思います。
duskwuffが提案したように、はるかに堅牢で「数学的な」解決策は、複雑な関数logと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
ます。それがなければ、統一のルーツはあまり意味がありません。それで彼らは非常に理にかなっています。