2015年08月31日の日記です

目次

08-31 夏の終わりの素数
08-31 DOSBoxで日本語表示・JP106キーボード・UBASIC


夏の終わりの素数  2015-08-31 16:58:07  コンピュータ 家族

▲目次へ ⇒この記事のURL

今年の春ごろ…長男が5年生に進級したころだったと思うが、こんな質問をされた。


1~100までのすべての自然数で綺麗に割り切れる数って、どんな数だろう?



一応彼なりに答えは持っているのだけど、その答えが大きすぎて算出できない、という。


長男の考え方はこうだ。


まず、100 までの素数を探し出す。

100以下の数は、これらの素数を適切な回数掛け合わせることで作り出せるはずだ。


だけど、これらの素数を全て掛け合わせても、問題の答えにはならない。

素数をかけるだけでは、素数である「2」で割れることは保証されても、4で割れることを保証できない。


2を適切な回数掛け合わせることで、この保証を作り出さないといけない。


この「適切な回数」は、掛け合わせた数が 100を超えない最大の値になるようにする。

2であれば、6回掛け合わせて 64 にする。64 で割れる数字は、32、16、8、4、2でも割れることが保障される。


同じように、3ならば4回掛け合わせて 81とする。

全ての素数に対し、この操作を行う。


そして、最後にこれら掛け合わせて出来た数を、すべて掛け合わせる。

その答えが冒頭の質問の答えとなる。



説明を受けて、なるほど、と思った。考え方はあっている。つまり、それが答えだ。

でも、その数を実際に算出できない。



長男の疑問には条件に入っていなかったが、この数は、条件を満たすうちの「最小の数」でもある。


(素数を使った考え方は、最小公倍数の求め方と同じだ。

 つまり、この数は1~100の最小公倍数である)




この時点で、長男はためしに 10 までの数値で試算を行っていた。

1~10 の自然数で割り切れる数は、2520 だった。


その疑問は、大きすぎて解決できない数としてそのままになっていた。



夏休みも終わりに近づき、長男は宿題を全部終わらせ、急に「Scratch って、どのくらい大きな数を扱えるの?」と聞いてきた。


なかなか難しい質問だ。

宇宙物理学などで大きな数を使う時には浮動小数点を使う、という話は長男は知っているので、コンピューターも浮動小数点を使えることを教える。


その上で、Scratch 内部では 64bit 倍精度演算を行っていて、正確に出せるのは 52bit 分だけど、大きな数の表現としては、さらに 11bit 分の指数が付けられることを教えた。


ややこしい話に最初は混乱していたけど、次に「指数を使うと、大きな数は表現できるけど、その場合は細かな数は出ない?」と聞かれる。


うん、その認識で正しい。正確な数を求めたければ、52bit の範囲に収めないといけない。


じゃぁ、52bit ってどのくらい? と聞かれたのだけど、即答できない。

32bit で40 億、さらに 20bit 余るけど、10bit で 1024 だから、40億の千倍の千倍くらい、と答える。



ここで、「じゃぁ、1~100までの全ての数で割り切れる数、計算できるかな」と言われる。

先に書いたように、冒頭の話は春のこと。僕はすっかり忘れていたけど、長男はまだ疑問に思っていた。


面白い、やってごらん、とノートパソコンの使用許可を出す。


#長男が Scratch をやりたいときは、僕か妻に許可をもらってノートパソコンを借りている。




1~100までの素数は知っているのだけど、うまくいったらもっと大きな数も計算してみたいので、と、エラストテネスの篩から作りはじめる。


素数を求めるアルゴリズムね。プログラムの初心者向けの課題として良く出されます。


普通は配列で作るのだけど、Scratch には配列が無い。でも、リストがある。

最初にリストに 2~100の数字を入れて、「倍数」はリストから削除していく、というプログラムにした。


リストの先頭を取り出すと、それは常に素数。

素数を取りだしたら、リストの数値を順次確認し、取り出した素数で割った余りが 0 なら、削除する。


最後に、取り出した素数は、素数を入れるもう一つのリストに追加される。



元となるリストがどんどん削除されていくので、終わりに向かって加速していくプログラムが出来上がった。

見ていてなかなか楽しい。



これで素数が得られたら、次にそれらの素数を掛け合わせ、100を超えない最大の数にした数値を、また別のリストに入れていく。


最後に、リストに入った数値を全て掛け合わせれば答えが出る。


結果は… 6.9720375229..e+40 !


…残念! Scratch では正確に求められないほど大きな数値だった。


#最後が e+40 となっているのは、52bit の範囲を超えてしまい、指数表現になったことを意味する。




プログラムを作って、答えは出たけど、正確な数じゃなかったーーー と、残念がりながらも面白がる長男。

せっかくなので、ここは父の威厳の見せどころ。


自分のマシンに向かって、UBASIC を起動する。

というか、以前にちょっと使ってみようとしたけど、使い物にならなくてほったらかしてあったのね。


UBASIC は、DOS 時代のフリー BASIC 。

実効桁数なんと 8640bit (540word) という恐ろしい演算性能を持つ。


DOS では動いたけど、残念ながら今の Windows では動かない。

でも、フリーの DOS エミュレータである DOSBox 上では動く。


…のだけど、DOSBox は英語版 DOS だし、キーボードも US 101 キーボードが前提。

これが「使い物にならない」としていた理由。


とりあえず、数値演算だけだから日本語は使えなくてもいい。

エラーメッセージが文字化けして読めないけど気にしない。

長男の考え方を、どんどんプログラムしていく。


…のだけど、流石に US 101 キーボード用は使いづらい。

いちいち記号を探すことになって効率が悪い。


ちょっと調べると、改造品で 106 キーボード対応があったので、DOSBox を入れ替える。

後で書くけど、その後さらに環境整えたら日本語も出るようになった

(この時は、BASIC プログラムを作ることが優先で、そこまでやってない)


久しぶりの UBASIC で無駄に手間取った部分もあるのだけど、2時間ほどで完成。


  100   Max=100
  110   dim F%(Max)
  120   for I=2 to Max
  130   if F%(I)=1 then 160
  140   F%(P)=I:P=P+1
  150   for J=I to Max step I:F%(J)=1:next
  160   next
  170   B=1
  180   for I=0 to P-1:A=F%(I)
  190   if A<Max/F%(I) then A=A*F%(I):goto 190
  200   B=B*A
  210   next
  220   print B

BASIC ではリストは使えないので、素数を求める部分は普通の配列。

1だと「既にチェックされた」、つまり倍数であることを意味している。


# F% というのは、UBASIC 独特の書き方。1word 数値であることを示す。

 0 か 1 かを保存するだけなので十分。

 こうしないと、540word の変数を配列にしようとして、すぐにメモリ不足となる。



120~160 で素数を求める。

130 で倍数か素数か調べ、素数なら 140 で記録、150 で倍数をチェックしている。


170 からは素数が求まった後で、190 で「100を超えない最大の倍数」にして、200 行でそれを掛け合わせている。



長男が求めていた答えは 69720375229712477164533808935312303556800 だった。




後日追記 2015.9.7


こういう計算なら、UBASIC より Ruby がいいと思うよ、という重要な示唆をいただきました。

恥ずかしながら、Ruby に多倍長型があるのを知りませんでした。


Ruby で書き直してみたプログラムを含め、ここら辺の話、別の日記に書いています



▲目次へ ⇒この記事のURL

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

コンピュータ

家族

関連ページ

プログラム教育に対する誤解【日記 16/03/19】

用語選びの難しさ【日記 15/09/03】

ruby で数値演算【日記 15/09/07】

別年同日の日記

10年 1回忌

16年 「人工知能」の生まれた日(1955)

17年 夏風邪


名前 内容

DOSBoxで日本語表示・JP106キーボード・UBASIC  2015-08-31 17:45:10  コンピュータ

▲目次へ ⇒この記事のURL

さて、先の記事に書いた UBASIC の話。

興味を持った人のために環境構築方法を書いておこう。


追記:2015.9.3

DOSBox の最近のバージョンを日本語キーボード対応したものがあったので、そのバージョンを使用するように書き換えました。


まず、DOSBox という、DOS エミュレータが必要になる。


DOS っていうのは、Windows が登場する前の OS ね。

Windows 95 までは、DOS の上に構築されていたけど、XP 以降は NT ベースになったため、DOS は無くなってしまった。


…はずなのだけど、Windows 7 でも 32bit OS なら UBASIC はコマンドラインで動かせた。

マイクロソフトの互換性確保の努力は驚異的だ。



64bit OS を使っていると、さすがに動かない。エミュレータが必要になる。

普通の PC エミュレータに DOS をインストールしてもいいのだけど、DOS エミュレータは最初から DOS を動かす前提で作られているので、手っ取り早いし扱いが楽。



でも、公式には英語版しかない。

DOS 自体が英語環境だし、キーボードも US 101 キーボードが前提。

配布されているバージョンも、もう長いこと 0.74 のままだ。


ただし、「ソースコード配布の公式バージョン」というものがあって、こちらはどんどんバージョンアップしているらしい。

いわゆるベータ版扱いで、使うには自分でコンパイルする必要がある。



これを、日本語キーボードに対応させた人がいる

ありがたく使わせてもらおう。




展開すると、dosbox-r3850-jp が出来上がる。


インストーラーとか無いから、適当なところに置く。

これで DOS エミュレータの準備は完了。ちょろいもんだ。


dosbox.exe を起動すれば DOS 画面が開くけど、DOS を使ったことがある人でも意味がわからないだろうと思う。

独自のコマンドとか入っていて、Windows との親和性を非常に高めてあるから。


DOSbox が他のエミュレータと違うのは、Windows のディレクトリを「そのまま」ディスクとしてマウント出来ることだ。


Windows の C: ドライブに \DOSBOX というディレクトリを作って、


mount c c:\DOSBOX


とすれば、DOSBox の中で \DOSBOX ディレクトリが C: に割り当てられる。

(もちろんディレクトリは別の名前でも構わない。僕は自分の documents ディレクトリの下に DOSBOX を作っている)




dosbox.exe と同じディレクトリに、dosbox.conf というファイルがある。

中身はあまり気にしないことにして、一番下を見ると [autoexec] というセクションがあって、当初は何も書かれていない。


ここにコマンドを書くと、起動時に自動的に実行される。

だから、ここに


mount c c:\DOSBOX

c:


と書いておくと、起動直後に c: ドライブのルートにいる形になる。

おぉ、DOS っぽい。




さて、これだけでは日本語は表示できない。


その昔、DOS/V パソコン、という言い回しがあったのを覚えている方はどれくらいいるだろう?


IBM-PC 互換機を日本ではこう呼んだのだけど、それは DOS/V と呼ばれる日本語 OS を使っていたからだ。

この DOS/V 、DOS に日本語表示のためのソフトを追加した、ただそれだけのものだ。


そして、当初は IBM が開発し、販売していた日本語表示ソフトは、ユーザーの手で互換品が作られ、配布されるに至った。

これらのフリーソフトを使えば、問題なく日本語が表示できる。



最初に概念を説明しておこう。DOS/V を知っている人なんて、あまり多くないからね。

DOS/V の日本語表示は「フォントドライバ」と「ディスプレイドライバ」に大別される。


フォントドライバは、フォントファイルを読み込んでフォントを提供する。

フォントが無いと何もできない。


ディスプレイドライバは、このフォントを使って画面を表示するのだけど、「英語モード」と「日本語モード」がある。

これを切り替えるための信号を送るためのソフトが無いと、日本語モードに出来ない。


というわけで、フリーのフォントドライバ、ディスプレイドライバ、フォント、モード切替ソフトが必要となる。




ここで一つ注意が必要だ。

dosbox には、デバイスドライバを組み込む方法が用意されていない。


デバイスドライバは基本的に「外部デバイス」を動作させるためのものであって、ソフト的なエミュレータでは必要ないでしょ、ということらしい。


幸い、日本語表示のための「デバイスドライバ」は、デバイスドライバと呼んでいるのが言葉の綾で、OS を拡張するアプリケーションに過ぎない。


昔の DOS を知らないとわかりにくい話なのだけど、デバイスドライバとアプリケーションは、ほぼ同じ構造なのだけど、ほんの少しだけ作り方が違った。

これを、巧妙な方法で「デバイスドライバとしても、アプリケーションとしても動作できる」ソフトとして作っている人もいる。



そこで、フォントドライバとディスプレイドライバは、デバイスドライバ専用として書かれたものではなく、アプリケーションとして動作できるものを使う必要がある。




ディスプレイドライバ DISPV


このページ、非常に古くて、なぜか文字が読めなくなっている。

CTRL+A とかして選択反転すると読めるのだけど、「ダウンロード」リンクだけは読めるので、とっととダウンロードさせてもらおう。

展開すると、WEB に書かれたのと同じ内容のテキストファイルが入っている。


これらの中身を、先に書いた c:\DOSBOX\ の下にディレクトリを作って置こう。

c:\DOSBOX\DISPV に置くことになる。


このディスプレイドライバは、IBM 公式の日本語ドライバの互換品を作る、という試みを始めた人の作ったドライバだ。


敬意を払ってフォントドライバもこの方のプログラムでそろえたかったのだけど、残念ながらデバイスドライバとしてしか、動作しない。



フォントドライバ FONTN


右側のペインから、fontn10.lzh を探してダウンロードしてほしい。

こちらがフォントドライバになる。アプリケーションとして動作できるので DOSBox でも組み込める。


先の DISPV と同じように、展開しておいておこう。

c:\DOSBOX\FONTN になる。



平木敬太郎フォント


X68k 用に作られたフリーフォントを、DOS/V 用にコンバートして配布している。

小伝馬町16が使いやすいと思うけど、16dot フォントであればある程度お好みで。


中身を、c:\DOSBOX\FONT に置こう。


#上記ページ、現在リンク切れ (2016.12.28)

 もっとも、waybackmachine には残っています

 FONTX2 形式の 16dot フォントであれば、ネット上で配布されている他のものでも構いません。



CHEJ


日本語と英語を切り替えるのに使うソフト。

最初は英語環境で始まるので、このソフトが無いと日本語を表示できない。


中身を、c:\DOSBOX\CHEJ に置こう。




さて、ファイルが揃ったところで、設定ファイルを書く。

フォントドライバに読み込ませるフォントを設定しないといけないのだけど、設定サンプルも何もない。


何も考えず、c:\DOSBOX\FONT\ の下(小伝馬町を置いたところ)に、FONTN.INI を作ってほしい。内容は以下の通り。



[CODE] ; Define code area.
F040 F0FC ; user font area
[FONT] ; Install font file.
GONHN16X.TLF
GONHN19X.TLF
GONZN16X.TLF


[CODE] 以下は、外字領域を指定している。

[FONT] 以下の内容は、先ほど展開した小伝馬16 のファイル名3つを書く。


HN16 は、縦16ドットの半角アスキーフォント。

HN19 は、縦19ドットの半角アスキーフォント。

ZN16 は、縦16ドットの全角日本語フォント。


半角フォントに 16dot と 19dot があるのが謎に見えるだろうけど、19dot は基本的に、下に3ドットの空白を入れただけ。


DOS/V では 25行モードと 30行モードがあるのだけど、縦方向が 480dot なので、1行の大きさは 19dot と 16dot になる。


英語のフォントで「罫線」があるため、縦方向に繋げるためには「25行モードでは3ドットの余白を入れる」というわけにいかず、19dot のフォントが必要となる。


これで、日本語を表示する準備が整った。




さて、いま入れたソフト群を使えるように、dosbox.conf の autoexec を追記する。

(さっき書いた、mount して c: する下に続ける)



\fontn\fontnx /P=c:\font\
\dispv\dispvb
\chej\chej jp
\dispv\vmx 70


フォントを組み込んで、ディスプレイドライバを組み込んで、日本語モードにし、縦 30行モードにしている。


ちなみに、\chej\chej us とすれば英語に戻る。

\dispv\vmx 3 とすると、縦 25行モードになる。


これで DOSbox を起動すると、自動的に日本語モードに切り替わるはずだ。




やっと下地ならしが終わった。

これで UBASIC を導入できる。


UBASICの配布ページに行って

ありゃ? しばらく前にダウンロードして自分のマシンに入れたはずなのだけど、今見たら繋がらない。


一時的な障害だと良いのだけど、Internet Archive に保存されたページをリンクしておこう。


配布ファイルも保存されていて、ちゃんとダウンロードできる。DOS/V 32bit 版だ。

ついでと言っては何だけど、その下にある「ヘルプファイル」もダウンロードすると良い。



これらを C:\DOSBOX\UBASIC\ の下に展開する。


DOSBox から、C:\UBASIC\UBV32.EXE を起動すれば、UBASIC が使える。

8640bit (540word) という驚異的な演算精度を持つ BASIC 。

その精度を活かし、複素数演算もできる。


当時は非常に標準的だった、Microsoft Basic に近い文法を持つ。知っている人ならなんとなくで使える。

詳細なリファレンスは、ヘルプファイルの中の UBHELP.XXX がテキストファイルなので読んでみよう。



実は、UBHELPV.COM を実行してから UBV32.EXE を実行すると「HELP」コマンドで UBHELP.XXX を項目別に分けたオンラインマニュアルを読める。

CTRL + \ で、カーソルが載っている命令の詳細がわかる。


…はずなのだけど、DOSBox 上ではなぜか不安定で、CTRL + \ は効かないし、ハングアップすることもあった。


DOS 環境上では同時に2つの作業は出来なかったので、このオンラインマニュアルは重宝したのだけど、Windows なのだから UBHELP.XXX をテキストエディタで開いて読むのでも良いと思う。




chej 、vmx 、ubv32 など、よく使うコマンドはパスを通しておくと使いやすい。

c:\chej\chej と入れる代わりに、chej だけで実行できるようになる。


dosbox.conf の autoexec に以下の行を追記する。



set path=c:\chej;c:\dispv\;c:\ubasic;



Windows でもコマンドラインを使う人は path 環境変数を知っているかもしれない。

セミコロン区切りで上の書式のようにディレクトリを列記すると、入力されたコマンドをそれらのディレクトリから探し出してくれる。




最終的に、ディレクトリ構成などはこうなる。



C:\DOSBOX\CHEJ\(CHEJを展開したもの)
         \DISPV\(DISPVを展開したもの)
         \FONT\(小伝馬16を展開したもの)
              \FONTN.INI
         \FONTN\(FONTNを展開したもの)
         \UBASIC\(UBASIC、およびヘルプファイルを展開したもの)


上記の C:\DOSBOX\FONT\FONTN.INI は自分で作る必要がある。内容は以下の通り。


[CODE] ; Define code area.
F040 F0FC ; user font area
[FONT] ; Install font file.
GONHN16X.TLF
GONHN19X.TLF
GONZN16X.TLF


適当なところに展開された、DOSBox に入っている dosbox.conf の最後の部分に以下を追記


mount c c:\dosbox\
c:
\fontn\fontnx /P=c:\font\
set path=c:\chej;\dispv;c:\ubasic;
dispvb
chej jp
vmx 70
cd \ubasic
ubv32



もし余裕があれば、dosbox.conf の中から「cycles=auto」と書かれている部分を探し出し「cycles=max」に書き換えよう。

昔のパソコンの CPU 速度のエミュレートをなくし、最高速で動作するようになる。


よくわからない人は書き換えないほうが無難。

遊ぶ分には、遅くてもそれほど問題ないから。




これで、DOSBox 上で問題なく UBASIC が使えるようになったと思う。


DOSBox を起動して、UBV32 コマンドを入力すれば BASIC 画面になる。



先に書いたプログラムを実行してみよう。


c:\DOSBOX\SAMPLE.UB の拡張子で上記プログラムをテキストファイルとして保存すれば、load "SAMPLE.UB" で読み込むことができる。(コマンドの最後はEnterを押すこと)


その後、RUN (これもEnterを押す)すると、実行される。



1~100の全ての自然数の最小公倍数が算出できる。

数が大きすぎて、UBASIC 以外の言語で処理しようとすると、いろいろと面倒なプログラムを作らないといけないのだけど、UBASIC なら問題なく扱える。


ちなみに、冒頭の Max を 100 ではなく、1000 にすると「1~1000の最小公倍数」になる。


EDIT コマンドを使うと、プログラムが表示できる。

PAGE UP / DOWN で画面を送り、カーソルを書き変えたいところに移動して、書き変えた後は Enter 。


#複数行を書き変えるときは、1行ごとに Enter する。

 BASIC では、カーソルは自由に動かせるが、基本的にコマンドを「1行単位」で受け付ける。

 冒頭が数字で始まる場合はプログラムの格納を指示した命令と認識されるため、各行で Enter が必要になる。



さて、UBASIC ではいくつまで計算できるだろう?

5000 は大丈夫だけど、10000 は桁あふれでエラーとなった。


どこまで可能かは確かめたのだけど、あえて書かない。

興味がある人は自分でプログラムを改造して確かめてみてほしい。




え? 日本語入力したい?


…残念ながら、ここに書いたのは「表示する」ための方法。

とりあえずは、UBASIC で数値計算したい、日本語で表示されるエラーメッセージも読みたい、という目的だったので、「入力する」必要が感じられなかった。


asave コマンドを使うと、BASIC のプログラムをテキストとして保存できる。

テキストファイルで日本語を書き入れ(シフトJISでセーブすること)、load で読み込みなおせばプログラム中で日本語を使うことも一応できる。



DOS 用のフリーの FEP が存在しないわけではないので、入れてみれば動くとは思う。

ただ、フリーで作られた FEP って、大抵実験的で癖が強いんだよね…


▲目次へ ⇒この記事のURL

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

コンピュータ

関連ページ

プログラム教育に対する誤解【日記 16/03/19】

用語選びの難しさ【日記 15/09/03】

ruby で数値演算【日記 15/09/07】

別年同日の日記

10年 1回忌

16年 「人工知能」の生まれた日(1955)

17年 夏風邪


名前 内容

【みっくん】 Windows10でdosbox-0.74-svn日本語動作、turboC-BGI動作確認OKです。安心しました。 (2017-02-21 13:56:50)

あきよし】 ZN16、正しく設定されてますでしょうか? 空白になるならおそらく日本語モードにはなっているので、フォントが読み込めていないように思います。 (2017-02-05 17:31:37)

【さむい】 こんにちは。有意義な記事ありがとうございます。日本語DOSVのソフトを動かしたく試させていただきましたが、日本語が表示されません。ただの空白になる。アルファベットは表示されます。すみませんが、ご助言いただけないでようか? (2017-02-03 20:57:08)

【ななーし】 早急な対応ありがとうございます。チャレンジしてみます (2016-12-28 12:23:58)

あきよし】 リンク切れ報告ありがとうございます。ネットアーカイブへのリンクと、そのほかの代替方法を追記しました。 (2016-12-28 10:52:57)

【ななーし】 こんにちは。平木敬太郎フォントがリンクが切れており、どのフォントを入れてよいか悩んでいます。よろしければご教授下さい。 (2016-12-26 13:04:30)


戻る
トップページへ

-- share --

9000

-- follow --




- Reverse Link -