2014年5月25日日曜日
これに時間があるときに書き足したり、推敲したりする実験
2014年4月6日日曜日
人で無しのための計算機理論入門 その10 プログラムの基礎 その4 地味だけ ど大事な論理式
さて、とうとう10回目になったこの「 人で無しのための計算機理論入門」。一応、情報機器を使用したり、それ以上にプログラムさえ書いたりして使いこなしたりする上で、基本的な事項をきちんと押さえておくことがいかに大事かということをお伝えできたと思います。ほら、基本理論て意外に大切でしょう?ということです。
マイナスフラグ: 計算の結果が負の時に1、そうでないときは0
というフラグを立てる、というお話をしました。
こういう風にフラグというもので計算結果を出したあと分岐をするということは何となくおわかりでしょうが、複数の条件が重なった場合の分岐はどうするか、ここで、論理式というものが必要になります。
たとえば、「もし、毎年4月はじめの日曜日 晴れだったら花見実行のメールをメンバーに出す だけど 雨が降ったら中止」というプログラムを書きたいとします。
・Dを日付型の変数と定義
・Dに今日の日付を記憶
・Dが
4月であるか?
かつ
最初の日曜であるか?
をそれぞれ調べるサブルーチンを呼び出し、
条件を満たせば、次へ進む。
そうでなければ終了
・天気は晴れ? =>花見メール
天気は雨? =>中止メール
というように要素を分解して表せば計算機のプログラム的になるのは分かりますよね。(その他の天候の時は空気を読めということです。空気読むのは日本人として大事ですよ、ほんとうに。それができないから(ry)
かつ
条件Bを満たす
というのは条件Aと条件Bが両方満たされて初めて次に進めるわけですから、ある条件を満たしたとき立つフラグを1それ以外を0とすれば、
条件Aのフラグ 0 1 0 1
条件Bのフラグ 0 0 1 1
AかつBをみたす? 0 0 0 1
となり、かけ算したときの計算の結果と同じです。これを論理積と言い、その筋の学問の記号では∧と表します(集合の積集合の記号∩に似ていますが、0か1の2値しかないので、どちらかに決まるということで尖っていると思ってください)。
また、同様に「または」、というのもありますが、表にすると
条件Aのフラグ 0 1 0 1
条件Bのフラグ 0 0 1 1
AまたはBをみたす? 0 1 1 1
となり、かけ算したとき計算の結果と同じです。これを論理積と言い、その筋の学問の記号では∨と表します(∧と同様に集合の和集合の記号∪に似ていますが、はやり、論理式では0か1の2値しかないので、どちらかに決まるということで尖っているわけです)。
他に、もちろん、否定(記号:¬)と言うものもありますが、これは
条件Aのフラグ 0 1
条件Aの否定 1 0
と、わかりやすいです。
こういう数式を扱う学問にブール代数というのがあるのですが、言語の中には0をFalse、1をTureと表現する、ブーリアン型というのがあります。これはブール代数からきているわけですね。
だから、プログラム言語によっては、分岐の条件の部分で0以外の値にすればとすれば常に真と判断するという言語もありまして、慣れないととわかりにくいバグになりますから、気をつけてくださいね。
最後まで地味なこの講座にお付き合いいただきまして本当にありがとうございました。まだ、葉桜の咲くこの時期にこうして一つ書き物を終了させることができたことを本当にうれしく存じます。
つたない講座でしたが、何とか終わらせることができましたのはみなさまのご声援と叱咤激励の賜であり、繰り返しになりますが、心より感謝の意を表させて頂きます。
2014年4月5日土曜日
人で無しのための計算機理論入門 その9 プログラムの基礎 その3 使い回して効率を上げよう
他から影響されない一つの独立した組にする。
(カプセル化)
異なるメソッド(method)と記述し、呼び出すときは、
[クラス名].[メソッド名]のようにして呼び出す
[クラス名].[変数名]
2014年4月3日木曜日
人で無しのための計算機理論入門 その8 プログラムの基礎 その2 変数とメモリの関係
もう書かなくて良いのかと思っていたら、なんだか書かないといけないような雰囲気。四月バカであるように祈りたいです(この部分は4月1日に書いています)。しかし体調はいまいちなんだけどねえ。また使いつぶされてる為の陰謀じゃないのか、と半分本気で疑っている現在。みなさまどうお過ごしでしょうか。
(※4月3日注記 などと書いていたら4月2日のニュースで、オバマ大統領の訪日決定しそうだとあり、かなりビクビクているところ。私なりに大急ぎで仕上げたのは言うまでもありません)
さて、分岐ができればループができるということは前回の図でもおわかりいただけるのではないかと思います。
となると、他にいくつかの予備知識が有れば、もう、プログラムも書けるんじゃないかな、と思うでしょう。かけると思うけど、世の中そんなに甘くはないけど、結構甘い。どっちなんだ。
あと二つ、いや、三つかな、お話しすれば、関数型と言われる言語であれば、そこそこなプログラムは書けるになると思います。多少、経験は必要でしょうが。
まず、前回のフローチャートで、変数を使っていますが、意味的にはおわかりいただけたでしょうか。
たとえば、
i=i+1
などというのは、計算機プログラム上よく出てくる表現ですが、これは、もともと、計算機のメモリのある番地の内容を変数iとして使用しますよ、ということから出てくる、一般的な数学では見かけない表現で、要するに変数iとして割り当てられたメモリの内容を1増やしなさいということを計算機に指示する表現です。
この命令は、計算機内部では、メモリの内容をCPUのレジスタに読んでそのレジスタの内容を一増やして、もとのメモリの番地に書き込むという作業が行われるわけですが、それ以前の重要な問題がありますよね。
すなわちまず、ある変数をメモリに割り当てる、という命令がたいていのコンピュータ言語では必要となります。(Rubyという言語では勝手にそのあたりの空気を読んでこっそりとやってくれたり、それ以外の言語でも、統合開発環境と呼ばれるプログラム作成用のアプリケーションソフトを使えば、プログラムの作成中に指摘してくれたりもするようですが)たとえば、C/C++と言われる言語であれば、
int i;
と、変数を宣言します。これは、C/C++言語では「変数iを整数型の変数として宣言します」と言う意味ですが、実際のプログラムの実行上はメモリのある番地に整数の変数iの内容を記憶する領域を確保して下さいね、と言う意味です。(なんだかちょっとプロセスというのが分かってきたでしょう?)
つまり、プロセスというのは、プログラムが実際CPUで実行される形式(これを機械語、あるいはマシン語とも言います)で表現されたプログラムと、このような変数の為のメモリの領域が確保されたものということです。
さて、プロセスが分かっていただいたところで、この節での大きな一つの目的は果たしたわけですが、せっかくだからもう少しプログラムを書く上で重要なことを説明しておきましょう。ここからは少しややこしくなりますので、分からなくてもかまいません。しかし、知っていると、後々プログラムを書く技法上でのいろいろな悩ましいことがらでスマートに解決できる、という点で違ってきますので、一応説明します。
上記の例で、変数iをメモリのある番地の内容とすることにしました。ところで、その変数iの内容がどの番地にあるかということをどこかに記憶しておかなければ、高級言語から機械語に翻訳するときなどで困ります。
C/C++言語などで言われる、いわゆるポインタというものです。
たとえば、変数iの内容を変数jと同じ内容にしますということを行うときに、我々は変数iが変数jと同じになればいいんだから、たとえば、
i=j
と表現すればそれで良いと考えますが、しかし、よくよく考えるとコンピュータでは、実は基本的には二種類のやり方があって、
1.変数iと変数jの内容を記憶するメモリの領域を
別々に二つ確保して、変数iの内容を変数jと同じにする
2.変数jの内容を記憶するメモリの領域を一つだけ確保し、
変数iは、変数jの番地と同じ番地を参照するようにする
という、非常に微妙な話があります。
1.を「値渡し」あるいは「内容渡し」、2.を「参照渡し」もしくは「ポインタ渡し」と言います。
一般的なコンピューターの高級言語は、変数と変数において「値渡し」であり、「参照渡し」は特別な指示をしないとできなかったり、そもそもサポートしていなかったりしますが、次回説明する予定のサブルーチンに値を渡すときに、言語によって元々の設定が「値渡し」か「内容渡し」かが異なりますから注意しておかないといけません。
「値渡し」であれば、たとえば、上の例では、
i=j
としたあとは、それぞれ独立した変数になりますが、「参照渡し」であるときには、iの内容だけを変更しようとしてjの内容まで変更する、ということが発生しますからね。
このあたりは本当にややこしくて、注意していないとバグ(コンピュータプログラムが考えているとおりに動かないときのミスをバグが紛れ込んでるという言い方をします)としても発見できにくいバグになりやすいので、「値渡し」か「参照渡し」かは、少しプログラムが書けるようになってきたら、で良いですので、いつも気をつけておいて下さいね
2014年3月24日月曜日
人で無しのための計算機理論入門 その7 プログラムの基礎 その1
この記事からしばらくプログラムについての基本的なお話をしたいと思います。例によってハードウエアに一番近い部分から、プロセスという概念がどうして必要になったかというところまでお話ししていく予定です。
まず、プログラムをするのに必要な最小限度の要素を考えてみることにしましょう。
実は処理の流れを図式化したものに、フローチャート(流れ図)と呼ばれるもので、日本工業規格(JIS規格)でもきちんと定義されていたりもします(JISX0121)。これは、たとえば、ISO( 国際標準化機構 )の品質マネージメント規格にISO9000シリーズというのがありますが、そこでそろえる書類の手順書などにも用いられたりして、汎用性が高いので覚えておいても損はないと思います。
ここでは、あまり細かいことまでは言わず、まずはごく基本的な次の5つだけ説明しておきましょう。
以上の五つとなります。これに時には矢印を加えて、処理の流れを表わすのですが、だいたい、上から下へ処理の順序を書いていくのがふつうです。
ここで、「その2」のCPUに必要な機能で説明していなかった分岐というものが出てきました。この部分について説明して、今回の記事は終わりたいと思います。
CPU何らかの計算をすると、計算の結果に応じてフラグというものを立てます。ゲームなんかをやっている人は、あるイベントをクリアするとフラグが立って次のステージに進める、などと使ったりしてませんか。あのフラグと同様です。
ただし、CPUが計算の結果立てるフラグは基本的には次の二通り。
0(ゼロ)フラグ:計算の結果が0の時に1、そうでないときは0
マイナスフラグ: 計算の結果が負の時に1、そうでないときは0
この他に、割り込みの信号が検出されたときに1となる、割り込みフラグというものもあります。
CPUはこのフラグの状態をみて分岐をします。
たとえば、ある二つの変数の内容が等しいかどうかが必要なときは、引き算をしてゼロフラグが0か1かという結果を見て分岐の処理します。
また、同様に大きい、小さいの比較は引き算をした結果、マイナスフラグが立っている(=1)か立っていないか(=0)ということで分岐を判断します。
このように、ごく単純なことに、我々の作業は分解されて計算機では処理されていくことを少しご理解いただいておくと、計算機に対する見方もまた違ったものになるのではないでしょうか。
2014年3月23日日曜日
人で無しのための計算機理論入門 その6 基本ソフトの基本機能(OSのカーネルについて)
・カーネル : http://ja.m.wikipedia.org/wiki/カーネル
・OS : http://ja.m.wikipedia.org/wiki/オペレーティングシステム
・システムコール http://ja.m.wikipedia.org/wiki/システムコール
2014年3月20日木曜日
人で無しのための計算機理論入門 その5 仮想メモリ
なんだか国際問題にまで関わってきているような気がするこの人で無しのための計算機理論入門。きっと気のせいだということで、話を続けたいと思います。
今回は今では当たり前になったOSの重要な機能の一つ、仮想メモリについてお話ししたいと思います。
以前「その2」で、内部メモリと外部メモリの違いは価格だけだということをはなしました。一方、「その3」では、OSが無い段階のプログラムでは、内部メモリの大きさにプログラムが依存する場合があるということをお話ししています。そのようなハードウエアの差異をなくすのがOSであるということでしたね。
そのことについて今回は少々詳しく説明します。今回、比較的高度に専門的な内容ですので、理解できなくてもかまいません。このあたりのことを知らないIT業界の人なんかいっぱいいます。また、その分説明も詳しくなるため、文章も長いです。
では、まずCPUがどうやってメモリにアクセスするのかということについてお話ししたいと思います。
その2で、CPUとメモリはバスというもので結びついていて、バスにはアドレスバスとデータバスがあるということをお話ししました。
このバスは、基本的には電気信号を通す線、つまり電線ですが、機能が高度になり、高速化の要求に従っていろ色々なことがやられるようになっています、が、ここではそこまで詳しい内容にはふれません。
前回(その4)CPUとメモリの両方に関することとしてビット(bit)という単位が関係するという話をしました。そこでは、ビットとはCPUとメモリが一度に処理できる二進数の桁数であり、CPUがメモリにアクセスするとき指定するメモリの番地を表すときの桁数でもあるという話をしたと思います。
つまり、CPUがメモリとデータをやりとりするときに使われる信号線がデータバス、メモリの何番地のデータであるかを指定するのがアドレスバスというわけです。
遅まきながら、計算機が2進数を使用する理由は、それが、電線に流れる信号が、ONとOFFだけで表せられるからです。このあたりのことは、いずれ機会があればデジタル信号処理ということでお話しできるかもしれませんが、今回はごくイメージ的に。たとえば、モールス信号のように、とんつーとんつーと信号のあるなし、あるいは信号の長い短いで通信していた頃を思い出して下さい。その方が、明らかに明瞭に遠くまで信号を伝えることができますよね。計算機の世界では、同様に簡単なことをいかに速く動作させるか、処理させるかというようなことが基本的な考え方です。
さて、話しは、CPUとメモリの話に戻ります。内部メモリは動作が速いけれど高価で、外部メモリは遅いけれど安価というお話をしました。だいたい、現代のパソコンやスマホで使われる内部メモリは一般にDRAMと呼ばれる半導体のメモリですが、動作は数nsから数十nsで動作するのに比べて、HDDドライブなどの外部メモリはそれよりも数百倍ぐらい遅かったりします。ビットあたりの価格も逆方向に同じぐらい違いますけどね。
ところで、「その4」で説明しましたが、32ビットでアクセスできるメモリアドレスの範囲は4G(ギガ)、64ビットだと16E(エクサ)でした。これに対して、現在の高機能スマホでもメモリは2Gが一般的。パソコンのCPUは64ビットが普通ですが、せいぜい8Gから16Gぐらいが一般的ではないでしょうか。つまり、CPUが指定できるメモリアドレスの範囲より、遙かに小さいことがわかります。
CPUは、基本的にメモリにアクセスする場合、単にアドレスを指定してその番地の内容を読み書きするだけ、です。一方、OSさんは、たくさんのプログラムが時分割で同時に走らせていることで、計算機では、あたかも並列に色々な処理ができるように見せかけています(これも、マルチタスクと呼ばれるOSの重要な機能です)あるいは、一つのプログラムでも、CPUがメモリアクセスできる番地いっぱいのデータを処理する場合もあります。
そのような場合、OSさんは、こっそりと、CPUさんをだまします。つまり、外部メモリにあるような、プログラムやデータもあたかも内部メモリにあるように見せかけて、CPUが指定する本来内部メモリにはないアドレスも、あるように見せかけてCPUに処理をさせるのです。このようなOSの働きによって、CPU側から見ると、あたかも広大なメモリ空間に何も考えずにアクセスできているようにみえる。そういうOSの機能のことを仮想メモリ、と呼びます。
ただし、CPUはハードウエア的には内部メモリにしかアクセスできないため、OSさんは、一生懸命できるだけCPUさんが早く処理をできるように色々予測しながら、内部メモリの内容が外部メモリの内容とあまり頻繁に入れ替えをしなくて済むように考えて処理をしています。このように仮想メモリという考え方によって、現代のCPUは内部メモリの大きさに関わらず、様々な処理を行えます。
ただし、処理の内容が大きく、一方それに比べて、相対的な内部メモリの大きさが小さいような場合、内部メモリと外部メモリとの間の内容の入れ替えをOSは頻繁にしないといけなくなります。これが、古いパソコンで、なにかあるとHDDがカリカリ動き出す理由です。
したがって、パソコンやスマホ、タブレットPCを長く使いたいならば、CPUの性能はもちろん、内部メモリ(一般にDRAMあるいはRAMとよばれる半導体メモリ)の大きさも重要です。個人的には、新しくパソコンを買うとしたら、一番高いCPUより、二番目に高いCPUを選択し、その分、メモリにお金を使う方が、長く使うことができると思います。私なんか、パソコンは8年前に買ったものですが、メモリは奮発して2G載せていました。さすがにそろそろ限界に近いですが、まだそれなりにではありますが、Windows8.1走ってますよ。

