2015年09月07日の日記です


ruby で数値演算  2015-09-07 12:53:11  コンピュータ

先日 UBASIC で 100 までの自然数の最小公倍数を求めた、という話を書いた。


そしたら、「ruby使えばいいのに」という重要な示唆をいただいた。


なるほど。調べてみると、ruby は UBASIC 以上の有効桁数で整数演算ができた。


僕は ruby 使いではないので知らなかった。教えてくださった方に感謝。




ruby は一度手を出したことがあったけど、勉強途中で頓挫したままになっていた。


手を出したのは、1999年。僕が会社勤めを辞めて独立した時だ。

当時は perl で WEB プログラムできる人材が求められていて、独立して perl プログラムで稼いでいた。



当時はネットが「新しいメディア」で、相場というものが存在していなかった。


学生がバイト気分で気軽に「プログラム書きます」なんて仕事を請け負っていたのだけど、生活が懸かっていないバイト気分なので、めっぽう安い。

でも、バイト気分なので責任感もない。金を払ったのに納期通りに上がってこず、催促しても「定期試験なんで」と仕事をしようとしない…なんて話も実際に聞いた。



で、そういう痛い目にあった人は、会社も設立して真剣に仕事を請け負っている、といえばそれなりの金額を出してくれた。


#当時は今みたいに1円起業はできず、会社組織にしている、ということが本気度を示す指標だった。



でも、痛い目にあった人でないと、学生バイトと金額を比較され、同じとまでは言わないが安くやってくれないか、と値切り交渉をされる。


割に合わない仕事も何度かやった。



そして、じゃぁほかの人がなかなか手を出していない言語をやってみよう、と ruby に手を出した。

perl を勉強していたころから、perl をさらに使いやすくした言語として、ruby の噂は聞いていたから。



しかし、当時 ruby はそれほど有名ではない言語。上に書いたように、perl 使いの一部が気にしていた程度。

そんなわけで、ruby を勉強し始めてすぐに、ruby ができたところで仕事はない、と気づいた。



ちょうど仕事で知り合った人に「PHP を覚えてほしい」と頼まれ、PHP の勉強に切り替えた。

その人は日本PHPユーザー会の創設メンバーの一人だった。


当時は PHP だって知られておらず、覚えても仕事がありそうにはなかったのだけど、ありがたいことに PHP はその後有名になり、PHP ができるのであればそれなりに仕事があった。




さて、上に書いた話で ruby で勉強したのは、perl の延長として使えそうか、という程度の調査だけ。

プログラムを組むために、条件分岐や繰り返しなどの文法構造は理解したけど、データ構造を勉強する前に頓挫した形。


なので、bignum なんて存在を知らなかった。


#1999年当時のバージョンでも bignum は存在したのかな…とネットで調査したところ、当時からちゃんとあったようだ。

 だから、単に僕が勉強してなかっただけ。



この bignum 、なかなか優秀で、存在を全く意識する必要がない。

意識しないでよいからこそ、当時気づいていなかったのかもしれない。



下に、先日のプログラムと同等の計算を行うプログラムを示しておこう。

アルゴリズムなどは、ruby 向けに多少異なる。



Max = 100
F = Array.new(Max/2-2) {|i| i*2+3}
P = [2]


while a = F.shift
  P.push(a)
  F.reject! {|i| i%a==0 }
end


b=1
P.each do |num|
  a=num
  a*=num while a<=Max/num
  b*=a
end
p b


大きく3つのブロックに分かれている。


最初のブロックは、準備を行っている。

最初の行で 100 と定義している。これで、100 までの自然数の最小公倍数を求める。


2行目では、3~100 までの奇数のリストを生成している。素数の候補だ。

3行目は、素数のリストの準備。唯一の偶数である2は、最初から入れてある。


中央のブロックで、エラストテネスのふるいを実行している。

奇数リストの先頭を取り出して、素数リストに入れる。

と同時に、reject を使って、奇数リストから、今取り出した素数の倍数を削除する。


最後のブロックでは、素数リストから順次値を取り出し、適切な倍率をかけ、b に掛け合わせていく。

最終的に b が最小公倍数だ。最後の行で表示している。



UBASIC では 6006 までしか計算できなかった。

6007 は素数で、それを掛け合わせると桁あふれしてしまうのだ。


しかし、ruby では 100000 でも計算できた。さすがに時間はかかるけど。

答えは、69528383... で始まる、 43452 桁の数値になった。




それはさておき、UBASIC インストール方法まで含めて書いたのは、実はそれなりの意図もあった。



まず一つ目は個人的な理由。

もともと計算は小学生の長男の興味で始まったので、長男に BASIC を教えようと思ったの。


特に書いてないけど、長男がエラストテネスのふるいを作る部分で悩んでいた時に、家にある初心者向けのテキストから、エラストテネスのふるいのサンプルプログラムを見せたのです。


でも、BASIC を理解していないと全く分からない。目の前にアルゴリズムの答えがあるのに、それが理解できない。

日本語環境まで整えたのは、長男に使わせたときに、エラーメッセージが文字化けするようでは扱えないためです。


でも、これだけなら家の中でやればよいことで、インストール方法まで明示する必要はない。




最近の言語は、グラフィックを扱うのにややこしい仕組みが必要なものが多い。

でも、BASIC 時代はグラフィックの扱いは簡単で、UBASIC も例外ではない。


そして、UBASIC では複素数演算ができる。


5年も前に「いつか書きたい」と宣言したまま一切書いていない、マンデルブロ集合の魅力について書くのに良いのではないか、と考えていた。


マンデルブロ集合って、非常に複雑で興味深い図形ね。

非常に複雑なのに、その図形を描くための方法は非常に単純。


Z = Z2 + C


という、たった一つの式を延々と計算し続けて、結果をグラフにすればよい。


ただし、Z も C も複素数、というのがみそ。たった一つの式ではあるけど、その式の意味が非常にややこしい。

当然のことながら、複素数の理解が必要。グラフとして示すので、複素数平面も知らなくてはならない。



さらに、一般の計算機言語では複素数を計算することができないため、実数部と虚数部を分離して計算するテクニックが必要になる。

画像の生成は非常に厄介だし、計算している座標系と、パソコン画面の座標系を変換するマッピングテクニックも必要となる。


UBASIC なら、複素数を計算できるし、グラフィックを簡単に扱える。座標系だって自由に変えられる。



なぜなら、UBASIC は高校生が数学に親しむために作られた言語だから。

「テクニック」が必要となる部分を、できるだけ言語側で吸収し、アルゴリズムの理解だけを求めるようになっている。



…と、熱い思いで語ったけど、実は先日以降実際にマンデルブロ集合を描くプログラムを作ったところ、あまりの遅さにどうしようか迷っている。

UBASIC でアルゴリズムの概要だけ示すけど、実行はお勧めしない、というような書き方になるかも。


ruby でも複素数演算パッケージは存在するようだし、これも ruby でやってもよいかもしれない。

こちらは、BASIC 程気軽にグラフィックを扱うことはできないようだけど、やはり描画パッケージ自体は存在する。




どちらにせよ、記事を書くとしたらだけどねー。

複素平面を理解してもらうためには、まず虚数の面白さから入らないといけなくて、そこで悩んでしまって書くのが止まっている。


一応、目標は「小学生でも理解できるようにしたい」ということなのだけど、虚数の必要性を伝えるのはなかなか難しい。




同じテーマの日記(最近の一覧)

コンピュータ

関連ページ

夏の終わりの素数【日記 15/08/31】

別年同日の日記

13年 余計なことをしたらしい。

14年 TenQ


名前 内容


戻る
トップページへ

-- share --

1000

-- follow --




- Reverse Link -