sqrt(平方根)の計算

math.dll - 永字八法の続きっちゃー続きかも。
NScripterネイティブで、平方根を求めるsqrtを実装してみた。
なんで「ネイティブ」にこだわるかと言えば、たとえばONscripterに移植とかを考えた場合、dllに頼っているとうまくいかないことが多いからだ。「うみねこのなく頃に」がONscripterやらMacやらでプレイできないのは、画面効果dllのせいなのはよく知られた話だ。

使い方

sqrt %result,%num

第一引数には結果を格納する数値変数を、第二引数には平方根を求めたい数値を入れる。
得られる結果は、端数切り捨てになった数値である。1000倍した結果が欲しければ、元の数値を1000000倍してからやってくださいな。(ただし、それであんまり大きな数値を指定すると、NScripterが扱えなくなってエラーになるけど)
もし、第二引数に0やマイナスの数値を指定すると、0が返されるようになる。

スクリプト

define節、game命令以上
mov %0,100 ; 適宜変更すること。
numalias sqrt_base,%0:inc %0
numalias sqrt_result,%0:inc %0
numalias sqrt_try,%0:inc %0
numalias sqrt_temp,%0:inc %0
defsub sqrt
game命令以下、start節以上
*sqrt
getparam i%sqrt_result,%sqrt_base
mov %%sqrt_result,0 ; 初期化
if %sqrt_base<1 return ; 0とかマイナスの数値はよう扱わんわ。
if %sqrt_base=1 mov %%sqrt_result,1:return ; 1なら1だよな。ショートカット
mov %sqrt_try,1
mul %sqrt_try,2
if %sqrt_try<%sqrt_base skip -1
div %sqrt_try,2
~
mov %sqrt_temp,%%sqrt_result+%sqrt_try
mov %sqrt_temp,%sqrt_temp*%sqrt_temp
notif %sqrt_temp>%sqrt_base add %%sqrt_result,%sqrt_try
if %sqrt_temp=%sqrt_base return ; ショートカット
if %sqrt_try=1 return ; 終了条件
div %sqrt_try,2
jumpb

仕組み

非常にナイーブな実装になっている。
基本的には、nに対する平方根を調べるのに、仮の平方根mを設定し、mを二乗してnになるかどうか(近似値かどうか)を調べ、そうでなければ仮の平方根mを増やし……と言うやり方である。
速度に差が出るとすれば、このmの設定、増やし方の部分の工夫であり、今回は2進数を使うことで最短回数で割り出せるようになった、はず。

追記

平方根 - Atelier de Muguet 制作記録でつっこまれたよアハハン。
ニュートン法は昔みつけて忘れてたー。
やっぱ数学はまじめに勉強せんとあかんなー。