<   2004年 12月 ( 11 )   > この月の画像一覧

スタックの概念は、多くの初級プログラマが分かったつもりになっている
ものの代表格です。

というのも、スタックについて解説している書籍がそもそも少なく、
また解説があったとしても、配列を用いて擬似的なスタックを作っただけで
話が終わってしまっているものが非常に多いためです。

スタックはそもそもCPUに始めから実装されているFIFO方式の機構であり、
メモリ上のスタック領域を使用します。利用目的はデータの一時的退避
ですが、関数を呼び出す処理もこのスタックにより実現されています。

スタックの位置はスタックポインタSPと呼ばれるCPUレジスタにより
管理されていて、PUSH,POP,CALL,RET等の命令により操作されます。

これらの命令はアセンブリ言語と呼ばれる低水準言語です。

自動変数などは、このスタック上に確保されてしまいますので、
画像データなどを配列でどかっとこの領域に確保しようとすると
たちまちオーバーフローを起こします。スタック領域はあまり
大きくないのです。

最近はC言語にしても、Javaにしても多数の入門書が出版されていて
誰もが簡単にプログラムを始められるようになりました。入門の
敷居が下がって誰もがプログラムを始めやすくなったのはよいのですが、
ハードウェアレベルの知識は全く・・・という人が多くなってしまいました。

特にメモリの知識はビル建築で例えるなら土台に相当します。土台がもろくても
ある程度の高さならたえられますが、ある高さを超えた瞬間一気に
崩れてしまうものです。

土台固めにはアセンブリ言語の習得が一番の近道です。
[PR]
by pcinfo | 2004-12-25 09:55
今回はBIOS(バイオス)の話をしましょう。

パソコンの電源を入れたとき、最初ディスプレイ上には一体
何が表示されますか?パソコンによって表示されるものに多少
違いはあるでしょうが、少なくともイキナリWindowsなどの
OSが立ち上がるということは無いはずです。

電源を入れてからOSが立ち上がるまでの間に、黒い画面が
出てきて変な文字が表示されたり、またはメーカーのロゴが
表示されたりしていませんか?

実はこの黒い画面の間にせっせと働いてくれているソフトこそ
がBIOS君なのです。


「Basic Input Output System」の頭文字を取ってBIOS、
バイオスと読みます。

OSとは何か?を知っている方は、まぁ大雑把にワープロソフト
やゲームソフトを使うための土台となっている基本ソフト
くらいに理解していると思います。

確かにOSは基本ソフトなのですが、残念ながらハードウェアの
設定などあまりに基本的すぎることまでは面倒を見てくれない
ようなのです。

そこで、OSの役割よりもっと基本的、言いかえるとハード寄り
の設定や調整などを行ってくれる基本ソフトが必要となってき
ます。その役割を果たすソフトこそBIOSなのです。


BIOSもOS同様ソフトウェアですが、OSのようにハードディスク
上に記録されているわけではありません。マザーボード上の
フラッシュROM上に記録されています。このフラッシュROMの
ことをBIOSチップなんて言ったりしています。

(フラッシュROMは、そうですね。今のとこは書き換え可能な
ちょっと特殊なメモリくらいに理解してください)

さて、パソコンは電源を入れますと、まずこのBIOSを読み込み
CPUに命令を出します。そしてハードウェアの設定等々を
終えた後で、OSをHDD上からメインメモリに読み込み、制御を
BIOSからOSに渡します。

このOSに制御を渡すまでがBIOSの役割なのです。
[PR]
by pcinfo | 2004-12-25 03:59
コンピュータは0と1の情報しか扱えません。
しかし、私達人間は「0100011100011」などど言われても
何のことやら全く理解不能なわけです。

私達は普段、パソコンを使って、文章の作成をしたり
画像を見たりを当たり前の様にしています。

当然、私達はディスプレイ通じてこれらのデータを見るとき、
画像のデータと文章のデータは別々のデータなんだという
ことは容易に判断できるでしょう。

ですが、残念ながらパソコン君には画像のデータだろうと
文章のデータだろうと音声データだろうと、
0と1の羅列にしか見えないのです。

パソコン君にとっては、あなたが恋人にあてたメールも
ただの0101、子供の運動会のデジカム動画もただの0101、
ダイヤモンド富士を見事に写した高性能デジカメの画像も
所詮0101にすぎんのですよ、わっはっは!!!
(一体何が可笑しいのやら・・・↑)

以上のように、コンピュータにとっては文字も画像も
「ゼロイチゼロイチ」の情報にすぎません。

しかし、私達にとっては文字データと画像データは別物で
あり、「所詮0101の情報にすぎない」からといって
コンピュータにこれらのデータをごっちゃに扱われては困る訳です。

従って、コンピュータにはデータの種類に応じた処理をして
頂かなくてはなりません。そのことを理解するには、第一歩
として、データの分類を理解しておく必要がありましょう。


本題です。コンピュータで扱うデータは

2進数・10進数などの「数値データ」と
文字や画像などの「非数値データ」に大別できます。

一見すると分類はこれだけで十分な気がしますが、
残念ながらそう簡単にはいってくれません。

例えば、2進数は小数の表現の仕方により
「固定小数点数」と「浮動小数点数」に分類されます。

また、文字にしても表現の仕方(コード体系)が様々あり、
例えば、ASCIIコード、シフトJISコード、Unicodeなどを
あげることができます。
[PR]
by pcinfo | 2004-12-25 03:58
誤差と一口に言いましても色々と種類がありますが、今回は
10進数の小数を2進数に正確に変換できない場合があるという
話をします。

これはどういうことかといいますと、例えば、10進数でも
1/3なんかは0.33333…となってしまい、

本来1/3を3倍すると1になるはずなのに
0.33333…を3倍しても0.99999…となってしまい、

両者の間に誤差が発生することが知られていますよね?


これと同様に、例えば0.1という10進数の小数は正確に
2進数で表現することはできません。

どのようになるかというと、

0.0001100110011001100...

というように循環小数として表されることになります。

さて、これが一体何の問題があるのかというと、
以下のプログラムを実行してみてください。
これは、0.1を1000回足し合わせるだけの単純なものです。


#include
using namespace std;

int main(int, char **)
{
float sum = 0.0f;

for(int i=0; i<1000; i++){
sum += 0.1f;
}

cout << "合計: " << sum << endl;

return 0;
}

さてどうでしょう。実行結果は期待する100という数値には
なってくれず、99.999となってしまいましたね。

10000回ループしてみると誤差はさらにはっきり現れ、
999.903となってしまいます。

もちろんdouble型にするなど精度を上げることで、
より正確な数値に近づけることは出来ます.

大切なのはプログラミングをする際には、

実数計算には誤差が伴っているんだ

ということを常に意識しておくことです。
[PR]
by pcinfo | 2004-12-25 03:57
まず、無限級数というのをご存知でしょうか?

例えば、
1+2+3+4+5+6+…… とか
3+6+9+12+15+…… などで、一般的な式で書くと、

a_0 + a_1・x + a_2・x^2 + a_3・x^3 +……

という風に、無限の和で表現できる式のことです。
(∑を使ったらもっとシンプルに表現できますね^^;)

で、ここからが本題なのですが、この無限級数を使って
皆様ご存知の指数・対数やら三角関数やらを定義する
ことが出来てしまうのです。

そのおかげでこれまで無関係と思っていた関数同士に
実に密接な関係があることが発見できるのです。

それ以外にも無限級数で定義するメリットがありまして、
それは"近似"に使えるという点です。

「近似」とは、例えば3.000000012とかいう数値があったとしますと、

「細かいことをガタガタ言うな、3ってことにしとけ!」

ってことです(^_^;)例えば、1980円の品物があったとしますと
頭の中でもう2000円と一緒って考えちゃいませんか?
意外と私たちは日常において近似をしているものです。

例えば無限級数においてxの値が0.1だったとすると、

a_2・x^2の部分だとx^2=0.01くらいのもんですが、
a_6・x^6とかなってきますと、x^6=0.000001となってしまい、

もうこの部分は無視しても構わなく思えませんか?
このように無限級数を用いた場合、第何項まで計算するか
により、簡単に近似をすることが出来るのです。

で、ある関数f(x)を考えるとき、この関数が無限に微分可能な
関数なら無限級数でその関数を定義しちゃうよん( ̄ー ̄)b

というのをテイラー展開と読んでいます。

テイラー展開(ウィキペディア)
http://ja.wikipedia.org/wiki/%E3%83%86%E3%82%A4%E3%83%A9%E3%83%BC%E5%B1%95%E9%96%8B
[PR]
by pcinfo | 2004-12-25 03:57
C言語やC++の参考書を見ても分かります通り
main関数は様々な書かれ方をしていますね。

例えば次のような書き方を目にします。

main()
void main(void)
int main()
int main(void)
int main(int, char**)
int main(int, char*[])
int main(int argc, char **argv)
int main(int argc, char *argv[])
int main( int argc, char *argv[], char *envp[])

頼むから一つに統一してくれよって気分ですね(--;)

最近のC/C++言語関連の本では
int main()
int main(void)
と書かれていることが多いようですね。
一番シンプルだからという理由で採用されているのでしょう。

コマンドライン引数を指定する場合は以下のように書きます。
int main(int argc, char **argv)
int main(int argc, char *argv[])

基本的にどちらの書き方でも構いません。
配列へのポインタでもポインタへのポインタでも。

ちなみにenvpは環境変数やらを知りたい時に使います。
まぁ、環境変数を知ろうということ自体があまりないので
滅多に見かけない形だとは思いますが。

さて、我がPCinfoではこの書き方を採用しています。
int main(int, char**)

本当は引数加えて以下のように書いてもよいのですが、
int main(int argc, char **argv)

この書き方で、プログラム内でこれらの引数を使わずに
かつコンパイラの警告レベルを高く設定した場合、

「おい!引数が使われてねーよ!」

とコンパイラが文句を言ってくるので、コマンドライン引数
を使わない場合はargcやargvを抜いた書き方をしています。

結局どの書き方がいいのでしょうかね?

私はC/C++でのプログラミングはコマンドラインありきで
考えていますので、基本的にmain関数は
int main(int argc, char **argv)

コマンドラインを使わない時でも、
int main(int, char**)
(※int main(int, char*[])という書き方も見かけます)

としています。おそらくmain関数の書き方が一つに統一
されるとしたらこれであろうと勝手に考えてますんで(^^;)

C言語の入門本にあるような簡単な書き方でも全く構わない
と思いますが、main関数の戻り値にvoidを使うのはやめましょう。

main関数の戻り値はプログラムが正常に終了したことを
OSに伝える大切な値ですので(^_^;)
[PR]
by pcinfo | 2004-12-25 03:56
数学的には位置(変位)・速度・加速度の関係は

   微分    微分
位置 → 速度 → 加速度
    ←     ←
   積分    積分

の関係にあります。一度理解してしまうと何てことないの ですが、Σ(シグマ)やら∫(インテグラル)やら訳の分からない記号のせいで数学や物理にアレルギーを持ってる方も少なくないでしょう。

数式でこれらの関係を表現すると難しく見えるかもしれませんが、プログラムでは非常に簡単に表現できます。


簡単に理解してもらうために1次元(直線)上での物体の運動を考えてみることにしましょう。

速度とは時間当たりの距離の移動量のことです。
位置p、速度s、時間tとすると、

for(時間t){
  位置p += 速度s
}

と表現できます。速度が0の時は位置の変化はありません。速度が1のときはループを繰り返す毎に1ずつ位置が移動していきます。当然速度が5のときは変位も5ずつです。

このように速度に変化のない運動を等速度運動と呼びます。

さて、加速度とは読んで字の通り"加わる速度"のことです。
加速度aを先ほどのループに加えてみましょう。

for(時間t){
  速度s += 加速度a
  位置p += 速度s
}

今度は時間t毎に速度が変化していようになりました。
初期値を位置p=0、速度s=0、加速度a=1とした場合、

時間t 位置p 速度s 加速度a
 0   0   0   1
 1   1   1   1
 2   3   2   1
 3   6   3   1
 4   10   4   1

という関係になります。

平面座標(x,y)や立体座標(x,y,z)について考える場合もそれぞれの成分に同様の処理を施せばよいだけです。


ベースとなる考え方は以上になります。

ただし、実際にプログラムをする場合、時間tの単位は秒になるとは限りません。ゲームプログラミングの場合、画面更新はFPS(Flame Par Second)という考え方を用います。

例えば1秒当たり60回の画面更新が行われる場合は60FPSとなります。

ゲームにおいてはFPSは30または60で固定することが一般的ですが、パソコンの環境しだいでこの数値は変動してしまいます。コンシューマと異なり、パソコンは所有者によりそのスペックに差があるのが当たり前ですので、プログラム側でFPS60で固定しても、その画面更新を実現可能なマシンスペックでなければ、想定より低いFPSになってしまうのです。

ですが物理シミュレーションにおいては、物体の移動量がFPSに依存して変化するようなことがあってはならないのです。

物体の移動遼をFPSに依存させないためにはどうすればよいか、それはまたの機会に解説します。
[PR]
by pcinfo | 2004-12-25 03:56
VC++でOpenGLを使うための設定方法を解説します。

OpenGLというのはDirextX同様にグラフィックス用の
ライブラリです。DirextXがゲーム制作をメインとした
Windowsマシン限定のライブラリであるのに対し、
OpenGLはOSに依存しない汎用性の高いライブラリです。

さて、そのOpenGLを使うためには、
dll、lib、 ヘッダファイルが必要となります。

以下のどちらのサイトからでもダウンロードできます。
http://www.opengl.org/resources/libraries/glut.html
http://www.xmission.com/~nate/glut.html

例えば下のサイトからだとglut-3.7.6-bin.zipを落とせば
よいことになります。ついでにサンプルプログラムの
glut-3.7.6-src.zipも一緒に落としていいでしょう。

ダウンロードしたら解凍後できたファイルをそれぞれ
以下のディレクトリにコピーしてください。

ヘッダファイル…C:\Program Files\Microsoft Visual Studio\VC98\Include\GL
lib…C:\Program Files\Microsoft Visual Studio\VC98\Lib
dll…C:\WINNT\system32

それが終わったらVC++の設定に移ります。
メニューのプロジェクト>設定>リンクのタブを開いたら
オブジェクト/ライブラリモジュールの部分に

opengl32.lib glu32.lib glaux.lib glut32.lib

を追加して書き込んでください。

以上で設定終了です。後は実際にプログラミングするときに
必要に応じてヘッダファイルをインクルードしてください。
[PR]
by pcinfo | 2004-12-25 03:55
ロケットが空に向かって打ち上がることができるのは、
地上に向けて燃料を燃焼させてエネルギーを噴出する反作用
として、空に向かう推進力を得ているためです。

例えば人が物体を押しているとき、人が物体を押しているのと
同じ力で人は物体に押し返されているのです。

この関係を作用と反作用といいます。

物体Bが物体Aに押される力をF_bとすると、その反作用として
物体AがBに押し返される力F_aはF_bに等しくなります。

F_a=F_b

ではここで問題。引越しのため冷蔵庫と洗濯機をトラック
まで運ばなくてはなりません。冷蔵庫と洗濯機は接触しており
冷蔵庫を押すことによって2つ同時に運んでいけそうです。

さて、このときあなたが冷蔵庫をFの力で押したとしましょう。
そのとき冷蔵庫が洗濯機を押す力はどのくらいになるのでしょう?

ちなみに同じFの力にはなりませんよ(^_^)
冷蔵庫の質量をm1、洗濯機をm2とした場合、運動方程式は

F=(m1+m2)a となります。

つまりあなたは冷蔵庫と洗濯機2つの質量に力を加えることに
なるわけです。それに対し、冷蔵庫が洗濯機を押す力は

F=m2・a となります。ここで、上の式より加速度は

a = F/(m1+m2) となりますので、下の式に代入すると

F=m2・F/(m1+m2) となり結論がでましたね。

ちなみに冷蔵庫が洗濯機を押す力と同等の力で冷蔵庫も
洗濯機に押し返されることになります。
[PR]
by pcinfo | 2004-12-25 03:54
最近ではゲームでもハードの性能が極端に向上したためか
物理計算をきっちりとするようになって参りました。

ああ、自由落下も等速度運動をしていたファミコン時代が
懐かしい(´~`)

さて、ニュートン曰くあらゆる物体の運動は次の法則に
従います。Fを力、mを質量、aを加速度として、

F=ma となります。

つまり、物体に加速度を生じさせるものこそが力なのです。

さて、ここで高校数学の復習。加速度とは速度の微分です。
そして、その速度は位置(変位)の微分な訳です。

ということで、以上より加速度aは位置の2階微分として
表現することが出来ます。ここで位置をx、時間をtとすると、

F=m・d^2/dt^2・x となります。(ええい!見づらい!)
※d^2は2階微分ですよ~って記号の代用ね
[PR]
by pcinfo | 2004-12-25 03:52