minetの日記: sinθ=1/xのときのcosθの近似式 で遊んでみる 7
yasuoka先生の日記に刺激を受けたので、頭の体操をしてみた。
cosθ = 127/128 のとき、 sinθ ≒ 1/8 であるらしい。
これを逆に、sinから導いてみる。
sinθ = 1/x としたとき
cosθ = √(1 - 1/x2) = 1 - 1/(2x2) - 1/(8x4) - …
と展開できるから、後ろの項はxが大きいとき(θが0に近いとき)急激に小さくなるので、第2項までで展開を打ち切ると、
cosθ ≒ 1 - 1/(2x2) = (2x2 - 1)/(2x2)
と近似できる。
よって
sinθ = 1/8 のとき、 cosθ ≒ 1 - 1/128 = 127/128
となり、yasuoka先生の近似と同じ値が得られた。
これだけで終わってはつまらない。
第3項まで展開した場合の近似式
cosθ ≒ 1 - 1/(2x2) - 1/(8x4)
= 1 - ((4x2 + 1)/(8x4))
をもうちょっと工夫して、精度と速度を両立できないか考えてみる。
適当にθを代入してみると
sinθ = 1/8 のとき、 cosθ ≒ 1 - (257 / 32768)
sinθ = 1/10 のとき、 cosθ ≒ 1 - (401 / 80000)
なのだが、これを具体的に計算してみると、なにやら、半整数の逆数に近い値が現れてくる。
1 - (257 / 32768) ≒ 1 - (1 / 127.5) ??
1 - (401 / 80000) ≒ 1 - (1 / 199.5) ??
といった具合だ。
これはどういうことかと言うと、
分母が大きければ、分母の値がちょっとだけ変わっても大差はない、と言うことは、
1 - ((4x2 + 1) / (8x4))
≒ 1 - ((4x2 + 1) / (8x4 - 0.5))
のように、分母をちょっと改善(改悪?)してやれば、
1 - ((4x2 + 1) / (8x4 - 0.5))
= 1 - (2 / (4x2 - 1))
= 1 - (1 / (2x2 - 0.5))
てな具合に整理できて、半整数の逆数が現れるわけだ。
ということは、
sinθ = 1/x のとき、
cosθ ≒ 1 - 1/(2x2 - 0.5)
= (4x2 - 2) / (4x2 - 1)
具体的には
sinθ = 1/8 のとき、 cosθ ≒ 1 - 1/127.5 = 253/255
sinθ = 1/10 のとき、 cosθ ≒ 1 - 1/199.5 = 397/399
てな具合に、良い感じに近似できる。
乗算除算がまともに扱えるCPUなら使えるテクかもしれない?
(とは言え、それが許される環境なら、もうFPUを使っても良い気がする。)
そもそももそもそ (スコア:2)
元ネタは、固定小数点的な何かっぽい気がするので。
Re:そもそももそもそ (スコア:1)
(なので、トピックは「プログラミング」ではなく「数学」にしてあります)
Re: (スコア:0)
8ビットに収まらないっす=>397/399
Re: (スコア:0)
回転行列だけなら表引きでいい気がするけどな。
背景を回転させようとすると誤差の累積とかいろいろ考えることがあって
そっちのほうが難しい気がする。
Re: (スコア:0)
8ビットマイコンだとテーブル引きも考えなしにできるものじゃないですけどね。
大抵、間接参照に使えるレジスタが限られているので。
Re: (スコア:0)
しかも8ビットの表なら256バイトもの「莫大な」メモリを使う
Re:そもそももそもそ (スコア:2)
恐らく1要素2Byte。
やり方によっては減らせるかもしらない。