2005-04-10 (日)
*関数電卓::逆三角関数と指数関数
わざわざ携帯電話で操作しにくい関数電卓を使う機会がどれだけあるか考えてしまう今日この頃です.
今日は逆三角関数やら指数関数をまともに使えるように.あとは,ニュートン法な平方根を実装.級数の収束条件があるので,色々と面倒くさい.とりあえず,値の大きさで場合分けして,加法定理とかでうまく収束するようにする.もっと良いアルゴリズムがありそう.速度を気にしないなら,ニュートン法とかでtanから求めても良いような….
asin,acosは作るのが面倒だったので,atanから求めるようにする.asin(x)=atan(x/√(1-x^2)),acos(x)=atan(√(1-x^2)/x)ですね.xが0とか1の時に不味いことになりますが,それは例外的に処理しましょう.
あとは,対数関数か…….ハイパーボリックな三角関数は個人的に需要が低いので後回し(普段の生活では殆ど必要ない気がするし).logはなんだか面倒くさそう….
n乗やn乗根ってどうやって求めるのが効率が良いんだろうか….とりあえず,平方根と立方根の組み合わせで計算しているけど,浮動小数点数の指数部の基数が10だったりするので効率悪い.やっぱり,コンピュータで数値計算するなら2進数でやるべきですね.
そういえば,階乗とnPrやnCrがまだあったな….今使っている関数電卓は階乗の計算は普通にかけているみたいで,数が大きくなると計算時間が微妙に長くなる気がする.まぁ,70!でエラーになるので,そんなに大きなものは計算できないのですが.
で,Windowsの関数電卓はどうも違うようです.((1/2)!*2)^2を計算すると円周率が出てきます.恐るべし.やっぱりガンマ関数を使うべきかな.
とうとうプログラムサイズが10KBを超えてしまいました(現在10,749Byte).動作確認のために,携帯電話にダウンロードするのもパケット代が気になってしまいます.今の機能なら,がんばれば10Kに収まるかも….
これはJavaなのか…
Javaにも演算子のオーバーロードが欲しい.自前のオブジェクトを使った演算をしている部分はまるでアセンブリ言語で書いてるみたいです.下の例はニュートン法で平方根を求めている部分.
do { //a=(a+x/a) / 2; d.set(x); d.div(a); a.add(d); a.div(c2); // d:= a^2 d.set(a); d.mul(a); } while (!d.isNear(x));
最初の式は「a.add(d.set(x).div(a)).div(c2)」と書くことも考えたけど,余計に分からなくなるので没.
というか,C++をJavaのバイトコードに変換するコンパイラってあったりしないかな.別にJavaが使いたいわけじゃなくて,JavaのVM上でプログラムを動かしたいだけなので…….
というか,DoJa3.0で実数が扱えないのがいけない.