IchigoJamでマンデルブロ集合

注意

2016年7月ごろの記事をもとにしています。 IchigoJamのバージョンも当時のものを対象としています。

IchigoJamは浮動小数点演算ができない?

それなら固定小数点を使えばいいじゃない。

固定小数点

IchigoJamの変数は16ビットで-32768~32767の整数を表せる。 この16ビットの途中のどこかに小数点があるものと考える、というのが固定小数点の考え方。どこに少数点を置くかは、必要な値の範囲と精度に応じて決める。 例えば、4ビット目と5ビット目の間に小数点があるものと考えると、上位4ビットが整数部、残りの12ビットが小数部なので、-8.000~7.999ぐらいの範囲の数を表せることになる。この型式を指して「4.12」とか言ったりするらしい。

固定小数点の足し算や引き算は整数型と全く同じでいい。でも掛け算とかでは小数点が移動することを考慮して補正する必要がある。 たとえば例のような固定小数点表現を普通の整数型として見ると、本来の値を左に12ビットシフトしたものになっているので、そのまま2つの値を掛け算すると、元の値を左に12x2=24ビットシフトした値になってしまう。

そこで、まず掛け算をする前に、それぞれの値を右に6ビット分だけ算術シフトしておく。 (今のIchigoJamの>>は論理シフトになるので、代わりに26=64で割り算すればいい。) そうすると、それらを掛けた結果はちょうど元通りのシフト量になる。

もちろん、掛け算の結果が範囲を超えた値になったらオーバーフローするし、最初に右シフトした段階で下位のビットが失われてアンダーフローもする。あらかじめシフトしておく量は合計12ビットならどういう組み合わせでもいいので、値の範囲があらかじめ分かっているなら、大きい方の値を多めにシフトするとかしたらアンダーフローは若干改善されるかも。

マンデルブロ集合

4.12の固定小数点で演算してマンデルブロ集合を描画してみるプログラムの例。 セミグラフィックの粗い解像度なら、演算の精度はあんまり問題にならないはず。(と考えてアンダーフローとかの件も考慮していません。)

ソース

1 'Mandelbrot set
10 N=32
11 W=64:H=48
12 A=2<<6:B=A*A:C=(3<<12)/W
20 CLS
21 forY=0toH-1:V=(Y-H/2)*C
22 forX=0toW-1:U=(X-(W*3)/4)*C
25 Z=#900+(X/2)+(Y/2)*32
26 J=1<<((Y%2)*2+(X%2))
27 K=J|#80|PEEK(Z)
28 POKE Z,K
29 P=U:Q=V:I=0
30 R=P/64:P=R*R:if P<0 GOTO40
31 S=Q/64:Q=S*S:if Q<0 GOTO40
33 if P+Q<0 or P+Q>B GOTO40
34 P=P-Q+U
35 Q=2*R*S+V
36 I=I+1:if I<N GOTO30
37 POKE Z,(K^J)
40 next
41 next
99 END

使い方

RUNするだけ。 全部描画するのに何分もかかるはず。(たぶんバージョンによっても違う)
ちなみにLPC1114が本気出したら数十ミリ秒とかそんなレベルになるらしい。

実行例

実行例