2014/03/30(日)Cardanoの公式とFerrariの公式

3次方程式の解法であるCardanoの公式、4次方程式の解法であるFerrariの公式、
数学の歴史で大変有名だけど、中身をよく吟味したことは無かった。
ちょっとしたきっかけで、これらをプログラムする機会があったのだが、
案外ややこしくて苦労した。Cardanoでは、複素数の3乗根を取る部分で3種類の解のうち
適切な1つを選ばないといけない部分があるのだが、こういうところがきちんと
書いてない文献が多かった。Ferrariでも平方根で同じような箇所がある。

最初はmathematica先生にSolve[a4 x^4 + a3 x^3 + a2 x^2 + a1 x + a0 = 0, x]とか投げて
出てきた式を適当に簡約化してこんなんでいいか、なんてやってたが、結果的にそれじゃ
使い物にならなかった。

CardanoやFerrariでは反復によらず直接解を計算するので、全計算過程を区間演算化すれば
容易に精度保証付きの解が得られる。と思って書いてみたが、ギリギリの計算が要求されて
ライブラリの問題点がいろいろ洗い出される結果に。
  • atan2([0, 1e-10], [-1, 1])のような場合に結果の区間幅が大きくなってしまう。
  • expに無限大に近いが無限大ではない数を入れたときの結果がおかしい (引数をfloorで丸めたものがintの範囲を超える場合)
  • 複素数の絶対値や平方根で(特に原点を含むような引数で)エラーになることがある。
  • ddの平方根に0を入れるとnanになる(newton法の失敗)
  • exp(interval<dd>(-1e308)*2)のような計算で無限ループに陥る
などなど。
複素数とddは実戦投入の経験が少なかったので、ちょうどいい訓練になった。
複素数の0に対してexp(log(0))がちゃんと0(あるいは0を含む微小区間)を返さなければ
うまく動かないようなシチュエーションも出てきて、intlabすらここはきちんと動かなかった。

最終的にはなんとか動くようになったのだが、CardanoはまだマシだがFerrariは素晴らしく
精度が出ない。doubleで平均的には7,8桁くらいか。
計算時間もかかるし、これらの方法が実際の数値計算法としてあまり使われない理由がよく分かった。
何でもやってみるものだなあ。

おかげでライブラリも結構アップデートしたので、ファイルの整理が出来たらversion upしよう。
OK キャンセル 確認 その他