そろばんをモデリングして、計算させてみようと思います。
昔、小学生の頃だったか、「そろばん塾」に通ったことがあります。その後も、あんまり暗算とかは得意ではないし、何より、そろばんを使った計算の方法は、もう欠片すら頭に残ってはおりませぬが……。単なる加算くらいなら、今から調べ直しても、何とかなるかな?、くらいな者です。
日本のそろばんは、1桁に5つの玉が連なっています。5つの玉は、「梁」と呼ばれる横棒で、上の1つと下の4つに分離されており、上の1つを「五玉」、下の4つを「一玉」と呼ぶそうです。桁と玉がバラバラにならないように、外側を枠で固定すると、「そろばん」になります。
この形って、日本で昔から使われていた物、何ですよね?って、紹介している作者が聞くのも何ですが……。と、言うのは、梁の部分に何桁毎かに印(「定点」と呼ぶようです)がついているのですが、どうやら、今のそろばんは、千進法(3桁毎)で印がついているみたいです。
ずっと昔の人たちは千進法で数を数えていたのでしょうか?日本の文化は、中国から伝わった文化が色濃く反映されているので、万進法(4桁毎)かと思っていました。
132,415,687円
もう慣れてしまいましたが、この数字を見て、パッと「1億3千2百万…円」と浮かぶまでには、結構慣れが必要でした。
1億3241万5687円 または、1,3241,5687円
上の様に、4桁区切りにした方が、日本の文化的には読み易いのに……。
塾に通っていた時に使っていたそろばんは、手元には残っていませんが、さすがに「木製」だった気がします。よって、前回(「つげ櫛」で)作った「つげ」のマッピングデータを使いまわすことにします。
※ちょっとお高そうな、「つげのそろばん(別ウインドウが開きます)」なんてあるの?と思って検索したところ、あるみたいですね。
今回のメインテーマは、「そろばんを使って計算している様子」を動画にすることです。
そろばんを使った計算は、「加算」くらいしか対応できそうにないので(他は忘却の彼方)、ただ単に、数列を加算して行こうと思います。1から順に足してもあまり面白くないので、最初に素数を求めておいて、素数を順に足していく動画にしようと思いました。
と、言うことで、まずは素数を求めるところから始めます。素数とは、「1と自分自身以外に割り切れない数」ですから、X=2から始めて、「自分自身−1」までの間に、余りが0になる数値Xが見つかったら非素数、見つからなければ素数と、判定します。
※もし、割り切れるとすると、最小の商は2のはずなので、「自分自身÷2」で判定を打ち切ると、ちょっと高速化できますね。
Xi-TRACEのデータでは、以下の様になります。
// 素数を求める
var idx;
var idx2;
var pnum0;
idx=2;
while (idx<NP)
{
idx2=2;
while (idx2≦idx/2)
{
if (idx%idx2=0)
{
break;
}
// 継続
idx2=idx2 + 1;
}
if (idx2>idx/2)
{
// 素数
static : var prim#(pnum0)=idx;
pnum0=pnum0 + 1;
}
// 継続
idx=idx + 1;
}
こんな感じなので、判定する数値が大きくなればなるほど、判定に時間がかかります。上のコードでは、変数NP未満の素数をリストアップして、配列prim#(idx)に蓄積します。
後ほどリンクする完成版のデータでは、加算と加算の間に一呼吸開けるため、配列prim#(idx)に素数以外の"0"をいくつか挿入しています。
次は、そろばんで加算する様子をシミュレートします。
「1,968+235」を計算してみましょう。そろばんでは、まず、定点に合わせて、「1,968」を打ち込みます。そこに「235」を加えるのですが、最初に「200」、次に「30」、最後に「5」を足し込んでいって、目的を果たします。
上のような手順を、1ステップづつCGに起こしていくと、そろばんで計算しているような動画が完成します。
※ああ、でも、やっぱり覚えていないな……。桁上げって、上の手順みたいに、後からやるんでしたっけ?指2本使って、同時にやっていたような記憶もアリ……。「4 → 5」にする時も、指1本で「五玉を下げる → 一玉4つを下げる」と、言う手順じゃなかったっけ?忘れちゃったな〜。
被加算数abac(=1,968)、加算数addc(=235)を、各桁毎に配列変数に分割するのは以下の様になります。
// 各桁に分離
idx=0;
while (idx<NC)
{
abac#(idx)=round (abac)%10;
addc#(idx)=round (addc)%10;
abac=floor (abac/10);
addc=floor (addc/10);
// 継続
idx=idx + 1;
}
この場合、配列の添え字0がLSB側で、添え字が大きくなるとMSB側となっています。
すると、1ステップ分の演算は、以下の通り。
// 1ステップ演算
idx=NC - 1;
while (idx>=0)
{
if (addc#(idx)!=0)
{
abac#(idx)=abac#(idx) + addc#(idx);
addc#(idx)=0;
if (abac#(idx)>9)
{
// 桁上がり
abac#(idx)=abac#(idx)%10;
addc#(idx + 1)=1;
}
lstx=NC/2 - idx - 2;
break;
}
// 継続
idx=idx - 1;
}
加算数addcの上位桁から、0ではない桁を探す → その桁を加算する → 桁上がりを判定して、addcの上位桁にセットする、こんな手順です。これを、addc=0になるまで繰り返すと、ようやく1回分の加算(abac=abac+addc)が終了します。
レイトレーシングしながら、このステップを計算していくのは、ちょっと難しいので、レイトレーシングデータとは別に、そろばんによる演算ステップをテーブルに出力するスクリプトを作っておきました(abacus_table.xitr)。レイトレーシングに先立って、1回実行してください。
完成したデータをリンクしておきます。
1) | Xi-TRACEデータ | abacus.xitr |
2) | マッピングデータ | comb_tuge.jpg |
3) | 演算ステップ計算 | abacus_table.xitr |
1)と2)でレイトレーシングを実行します。レイトレーシングの際に、3)で作成したテーブルファイルが必要となりますので、レイトレーシングを実行する前に、一度、3)を実行してください。
800未満の素数をすべて、そろばんで加算しています。最後の素数は797で、2から数えて139個、合計は50,078でした。「ごめいさん」……たぶん。