2ntブログ

1バイトに複数のデータを保管する

圧縮とかの話ではありません。
1バイトには1つのデータしか保管できないと思い込んでいる人へ、プログラマとして、IT技術者としてステップアップしてもらうためのマメ知識です。

世の中のデータには、文字や音声が画像や様々なものがあります。
コンピュータではこれらのデータを全て数値に変換して保管します。
したがって1バイトには1文字、あるいは最小単位の時間の音声、1ドットの画像データなど1つづつしか保管できません。
これらは0~255までの256種類の、あるいは256段階の数値に変換されて保管されるためです。

しかしデータの中には、たった2種類しか必要としないものもあります。
例えばインターネットで何か会員登録する場合、男か女か、既婚か未婚か、メールマガジン配信の要・不要などは、数値に変換しても0か1か2種類で表せます。
こういったデータは1バイトの中に複数保管する事が可能です。

なぜなら1バイトは2進数8桁で構成されているからです。
つまり1桁目は性別、2桁目は既婚・未婚、3桁目はメールマガジンの配信の要・不要などというように2進数を使った保管をすれば、8桁分、つまり8個分の2択データを1バイトに保管できるのです。

フラグデータ

図で表すとこんな感じでしょうか。

こういった0か1かで表せるタイプのデータを「フラグ」と言ったりします。
「俺、この戦争が終わったら結婚するんだ・・・」は死亡フラグとして有名ですが、あの「フラグ」も同じ意味ですw
この台詞を言ったか言わないかで、その後のキャラクターの生死が別れるわけですが、この言ったか言わないかという2択のデータなので、「フラグ」なのです。

さて、このようなタイプのデータを実際に保管したり、保管状況を調べたりするにはどうしたら良いでしょうか?

コンピュータの開発言語には、様々な命令(コマンド)があります。
その中にビット演算という種類のものが、たぶん大抵の開発言語にはあるはずです。
フラグ形式のデータを扱う場合は、このビット演算を使います。

ビット演算は

任意の変数 ビット演算命令(記号) 任意の数値又は変数

という形式で書きます。

ビット演算命令には

・AND
双方のビットが1の場合のみ、計算結果のビットが1になる
1 AND 1 =1
0 AND 1 =0
0 AND 0 =0

・OR
双方のビットが1又は片方が1の時、計算結果のビットが1になる
1 OR 1 =1
0 OR 1 =1
0 OR 0 =0

・XOR
双方のビットが異なる場合のみ、計算結果のビットが1になる
1 XOR 1 =0
0 XOR 1 =1
0 XOR 0 =0

の3種類が主に使われます。

1桁目のビットだけONにしたい場合は、
A=A OR 1
1桁目のビットだけOFFにしたい場合は、
A=A AND 254

1桁目のビットがONかOFFか調べたい場合は、
IF A AND 1 THEN ~
などのように書けばAの他の桁がどんな状態でも、1桁目が0なのか1なのかを判別させる事ができます。
ちなみに通常BASICなどは、ANDという英単語がビット演算命令ではなく、条件追加の意味だったりする事もあるので、詳しくはお使いの開発言語のリファレンスを見てください。

なお10進数表記でビット操作する場合、2進数⇔10進数の概念というか計算ができる必要があります。
基本的に2進数は1桁目から8桁目まで、それぞれが1だった場合、
1・2・4・8・16・32・64・128
という具合に10進数だと倍の数字になっていきます。
なので例えば1桁目と3桁目が1の場合は、1+4で10進数だと5になります。
つまりA=A OR 5 とした場合は1桁目と3桁目のビットが必ずONになるという事です。
1桁目が0でそれ以外が全部1の場合の8ビットデータは10進数に直すと255-1で254です。
(8ビットすべてがONの場合は10進数では255というのを覚えていれば、1桁目のビット分の数値をそこから引けば良いと分かると思います)
よってA=A AND 254とした場合は1桁目だけが必ずOFFになるという事です。

フラグ化できるデータをこのような方法で使うと、プログラム実行時のメモリやデータ保管時のHDDの容量が節約できるばかりでなく、動作スピードも速くなります。

ファミコンや8ビットCPUのパソコンしか無かった時代のプログラマは、全員知っていた方法です。
なぜならその時代はメモリはめちゃくちゃ少ないし、CPUもめちゃくちゃ遅かったので、少しでも少ないメモリで高速動作するように、プログラムを組む必要があったからです。

どんな初心者・ド素人が作ったプログラムても、豊富なメモリと有り余るCPUパワーで動作してしまうのが今の時代ですが、こういった知識・テクニックを知っているのと知らないのでは、差がつきます。

精進して下さい。

16進数とは?

16進数とは、16で1桁増える数字の表記の仕方です。
私たちが普段つかっている数の数え方は、10進数です。
現在世界共通で使われている数字は0~9までの10種類しかありませんので、16進数で10~15までの数値を表すときは、英語のアルファベットを使います。
つまり10=A 11=Bという具合に。
だからコンピュータのプログラムとかメモリの中とか覗くと、1AとかFEとか数字に混じって英字が入っているのです。

コンピュータのメモリ・HDDなど記憶装置の容量を表す○バイトという単位ですが、1バイトは16進数2桁の数値が保管できる大きさです。
このようにコンピュータの世界では16進数が全ての基本になっています。

ではなぜ馴染み深い10進数ではなく、16進数をコンピュータの世界では使うのでしょうか?

ご存知のようにコンピュータというのは、もともと2進数しか理解できません。
それは昔のCPUでも今のCPUでも同じです。
デジタルというデータの記憶形式も2進数です。
コンピュータが10進数でなく、2進数を基本として動作するよう設計されているのは、それが一番エラーが起きないからです。
正確性が求められるコンピュータでは、気温や湿度、電圧・電流、部品間をつなぐ線やケーブルなどの長さや抵抗などの要因によって、2が4になってしまったり、5が1になってしまったりしたら困るわけです。
2進数であれば0か1かしかありません。
電気が流れたか流れてないか、スイッチがONかOFFか、白か黒か、その2通りしかないので、ほとんど間違いようがないのです。

だからコンピュータは2進数しか認識できないように作られているのです。

しかし2進数しか扱えないとなると、0か1かの2種類の数値しか扱えないくて困りますよね?
そこで桁数を増やして、1つの数値データとして扱う事にしました。
2進数の桁は「ビット」という言葉で表されます。

今のパソコンなどの基礎仕様が固まったのは、8ビットの時代です。
8ビット=8桁の2進数で表せる数値は0~255までの256種類です。
10進数でこれを表記しようとすると3桁分の表示枠を用意しなければなりません。
かといって9より上の数字を1文字を表そうとすると、既存の文字では足りません。
英語のアルファベットを大文字・小文字すべて使っても26×2で52文字しかありません。
とてもじゃないけど足りないし、そもそも人間が10以降255までの数値を表す新しい文字を覚え切れません。
そこで10~15までの数値をA~Fで表す比較的覚えやすい形式の16進数が表記方法として採用されたのです。
16進数であれば1バイトは00~FFまでの2桁で全て表す事ができます。
現在は64ビットCPUが主流ですが、未だに1バイトが8ビット分のデータしか保管できない仕様のままなのはこのためです。

外的な影響を受けにくい2進数でデータを扱い、表記する時は人間が見ても理解しやすい16進数を使う。
これが現代のコンピュータの基本的な仕様なのです。

よって、少なくともプログラマを名乗るなら、この概念は理解しておかなければなりません。
プログラマでなくとも、たとえば企業向けのシステムを構築するために、必要なサーバや記憶装置を用意するような仕事をしている人も、1バイト=0~255までしか記憶できない事を知っていないと、必要なメモリやハードディスクを見積もれません。
文字などは1文字2バイト(英語なら1バイトで済みますが)で計算は簡単ですが、数値データの場合、たとえば人の年齢や生年月日や入社日や、そういったものの保管には何バイト必要なのか?はそれが255までの数値で収まるものなんか、そうじゃないのかによって1バイトなのかそれ以上のバイト数が必要なのか計算しなければなりません。

ちなみに人の年齢は常識的に考えれば1人あたり1バイトで済みます。
人間の寿命なんてどんなにがんばっても100何歳までです。
256歳以上生きる人がいれば、2バイト分枠を取らなければなりませんが、そんな人いませんからねw

こんな具合です。
要は10進数で255以内に収まるデータなのか256以上のデータなのかは最低限、それによって仕様が大幅に変わる事をとりあえず知っていればおkです。

プログラムは難しくない

プログラムは決して難しいものではない。

たとえば日本語の単語や文法を知っていても、それで小説を書くのは容易ではない。
楽譜の読み書きが出来て、音楽の文法とも言える楽典を勉強したとしても、作曲家になれるわけじゃない。
漫画なんてもっと難しいだろう。

それらに比べたら、プログラムなんて使う開発言語のコマンドと文法さえ知っていれば、誰でも書ける非常に簡単な創作作業だ。
そもそも全てのコマンドや文法を覚えている必要すらない。
こんな命令ないかなーってネットでコマンド調べたりしながら作ってたぐらいだ、私なんかw
そんなんでも、社員検索システムや、コード番号の生成システム、入力されたデータを一定の法則で整理して加工するバッチ処理など作れてしまう。
画面上をキャラクターが動き回り、敵と遭遇したら戦闘になり、経験値を貯めてレベルアップするようなゲームでさえ、作れてしまう。
まぁゲームの場合は、動くものが作れるのと、それが面白いかどうかはまた別の話だがw

日本でプログラマがIT土方などと呼ばれ、低賃金・重労働の典型のように言われるのは、「誰でもできる」いわゆるスーパーのレジのパート・アルバイト並みに簡単だからだ。
逆に本来の意味の土方である建設作業員は、体力はもちろんだが知識や経験も必要で、簡単にできる仕事ではない。
プログラマより建設作業員の方が、よほど難しい。
だから彼らは見下されながらも、高給取りなのだ。
ベテラン建設作業員が「職人」と呼ばれる事はあっても、ベテランプログラマが「職人」と呼ばれる事はない。
そもそもベテランプログラマなんてものは、日本にはあまり存在しない。
なぜなら薄給なので、若いうちは良いがある程度の年齢以上になると、それでは家族は養えないからだ。
SEというひとつ上の職になるか、課長・部長など経営陣側に出世しなければならないのだ。

プログラマにも力量差というのはある。
小学生の読書感想文かよwって下手糞な小説もどきと、村上春樹が書いたのかと思ったっていうぐらいオシャレな文章の小説との違いぐらいの。
ただ現代のシステムのプログラムは、「仕様書」通りの動作をすれば、中身が読書感想文だろうが村上春樹だろうが「納品」できてしまうのだ。
他のプログラマの作ったものより、高速で動いたり少ないメモリで動いても「評価」されないのだ。

良いことだとは思わないが、実際そうなのであるw
だから誰でもできる非常に「簡単」な職業であると、私は言うのだ。

もっともいくら簡単だと言っても、プログラムをまったく組んだ経験の無い人間がいきなりプログラマになれたりはしない。
英語をまったく知らない、聞いたことも見たことも無い人間が英語教師になれないのと同じで、ある程度の勉強は必要である。
ただ何かひとつの、それこそBASICでもいい、それらでプログラムをいくつか組んだことがあれば、あとは開発言語がCになろうがJavaになろうがコマンドと基本的な文法を調べるだけで、誰でもプログラマにはなれる。
I hava a penを知っていれば英語教師になれちゃうようなものだ。

プログラマの求人募集とか見ると、Cでの開発経験者とかJavaの分かる人とか応募資格が書かれているが、アホかと思う。
開発言語の種類なんて、英語とか日本語とかフランス語とかの違いにすぎない。
要は「言葉」を喋れる「人間」であるかどうかだけで良いのだ。
何かの開発言語で何かプログラムを作った経験のある人、これでよいのだ。
あとは辞書を引きながら、片言の英語しか喋れなくても、ネイティブ並みにペラペラの英語喋れても、変わらないからだ。

小説家や漫画家になりたい、作曲家・作詞家・シンガソングライターになりたいとか思っても、それに実際になれる人は少ないが、プログラマはなりたいと思ったら誰でもなれる職業なんですよって話です。

プログラマによる差が出る訳

プログラムとは、同じ処理を行うものでも、実現方法がいくつかある。

リアルの世界でどこかへ行く場合に、いくつかルートがあるのと同じだ。
「乗り換え案内」系のアプリは、社会人なら使った事があると思うが、あれで自分が今居る駅から目的地までのルートを検索すると、いくつか候補が出てくるのと同じだ。
到着時間が早いもの、運賃が安く済むもの、あるいは乗り換えが無くて楽なものとか。

どのルートを選ぶかは、その時の状況や個人の好みによるだろう。
プログラムの場合も、どのルートで処理を実現するかはプログラマの好みや経験によって大きく変わってくる。

経験が浅かったり、無能なプログラマだと、ものすごい遠回りなルートを選んだり、すごく運賃が高いルートを選んでしまったりする。
もっとも安くて早く目的地まで着くルートを選択するのは、昔と違って複雑なシステムが多くなった今は非常に難しい。
そもそも「乗り換え案内」のように、プログラムの処理のルートである「フロチャート」の候補をいくつか示してくれる便利なアプリとかは無いわけで。

「仕様」という目的地に向かって、どういうルートで進む(処理)するかは、すべてプログラマ自身が考えなくてはならない。

またどの命令(コマンド)を用いるかによっても大きく変わってくる。

Z80というパソコンには使わなくなったが、今でも多くの工業製品で使われているCPUで、例えば何かの値に1を足す処理をしようとすると、
ADD A,1
又は
INC A
という2通りの命令が使える。
前者はレジスタに任意の数値を加算する命令で、後者はレジスタの値を1だけ増やすという命令。
前者は1以外の数値も加算できるが、その代わり命令の記述に2バイト必要で、処理スピードもその分掛かる。
後者は1しか足せないが、命令の記述は1バイトで済み、処理スピードは加算命令としては最高速である。

マシン語でプログラムするなら、その時々によって最適な方を選択する事ができるが、現在開発に使われる言語はこのCPUが直接理解できる命令と1:1の、いわゆるアセンブラと言われるものでなく、開発言語独自の命令が使われ、「コンパイル」という処理をする事によって、開発言語のツールが独自命令をマシン語に直すのだ。
よって、「これは単に+1をしているだけだから、INC Aの方が速いしメモリも食わないからこっちでコンパイルしよう」とかやってくれないのだ。
足し算のソースは全てADD A、n(nは任意の整数)の方でコンパイルされるのが普通だ。

つまり本当に最小限のメモリで超高速に動くプログラムを作ろうとしたら、「アセンブラ」で組まなければならないのだ。
なぜいまそうなってないかといえば、メモリ容量がZ80というCPUが主流だった頃よりも格段に増え、またCPUの処理スピードもめちゃくちゃ速くなったので、そこまでプログラムの大きさや速さに拘らなくても問題なくなってしまったからだ。

とはいえ、塵も積もればなんとやらで、プログラマにより同じようなアプリケーション・処理でもアホみたいに遅いとか、メモリ食いまくるとかってのも良く見る。
プログラムだけじゃなく、例えばネットゲームの大型アップデートなんかでも、数十分もしないで終わるゲームもあれば、1時間以上も永遠とアップデートに時間が掛かるのもある。
理由は明白で、実行ファイル(exeファイル)やデータファイルをそのまま送ってくるアホ運営と、きちんと圧縮を掛けて送ってくるまともな頭の運営の違い。
ス○エ○とか前者ですね。
何度か改善要望とか出しても、理解できないのか、しまいにはユーザーの回線やPCの性能がショボイせいだろwwwってことになって低速回線・ボロPCお断りにしたほど。

コンピュータの性能が上がりすぎたが為に、こんなやつ等でもIT企業の技術者です(ドヤァ)できるようになってしまったんですね。
悲しい事です・・・

32ビットOSのメモリ制限はなぜ存在するのか?

32ビット版Windowsはなぜ4GB以上のメモリを積んでも使えないのか?
なぜ1アプリケーションにつき最大2GBまでしかメモリを使う事を許してないのか?
仮想メモリは何のためにあるのか?
というお話。

まずコンピュータの核であるCPUは、全ての計算処理を2進数で行っています。
電気が流れなかったら0、流れたら1という0と1しかない世界です。
ただこのままでは2以上の数値を扱えませんので、桁を増やして対応しています。
我々が日常で使っている10進数も、実は0~9までしか数字の種類はありません。
10以上の数値を表す場合は、2桁以上にして表記しています。
これと同じように2進数も2以上の数値は桁を増やせば表せるって事です。
つまりビットとは桁の事です。
32ビットOSあるいは32ビットCPUと言ったら、最短で処理できる数値が2進数32桁分って事です。
2進数32桁で表せる数値は、0~4,294,967,295です。
この4,294,967,295が、メモリで言うところの4GBになるわけです。
CPUは、今現在メモリのどの部分にある命令を実行しているかというのをプログラム・カウンタという内部メモリに記憶しています。
このプログラム・カウンタはOSやCPUのビット数と同じなので、32ビットOSやCPUはメモリを4GBまでしか使えないのです。
もっと増やせよwwwと思うかも知れませんが、この仕様ができた当時は4GBものメモリは大容量であり、それ以上必要になることはまずないだろうって考えられていたからです。
そもそも昔のパソコンやファミコンは、メインメモリの容量は1MBも無いんですよ。
それでもゲームが動いてたわけです。
4GBとか、そんなにメモリ使うプログラムとかシステムとか考えられなかったんですね。
今は64ビットOSがあり、32ビット版Windows使ってても、よほど古いパソコンじゃなきゃ、CPUは64ビットです。
ですがたぶん数年後なのか数十年後なのか、あるいは数百年後には「たりねーよwww」って話になってると思います。

さて4GBという限られたメモリでWindowsとアプリケーションの両方を動かさなければなりません。
Windowsは結構メモリを食うシステムなので最大で2GBメモリを使います。
なのでアプリケーションは残りの2GB以内で動くように作ってねってなってるわけです。
仮に超メモリ使わないOSだったとしても、32ビットである限りは4GB以上のメモリはどちらにしろCPUが処理できませんから。

でもこれだと何かのアプリケーションが2GBギリギリ使ってしまったら、もう他のアプリケーションは起動できなくなってしまいます。
マルチタスクOSってのは同時にいくつものアプリケーションが起動できるのが売りなので、これでは困ります。
そこで登場したのが「仮想メモリ」です。
OSやCPUがマルチタスク・マルチコアになったとは言っても、基本的に実行できるプログラムは1つだけです。
同時に複数動いているように見えますが、あれは複数のプログラムをちょっとづつ実行しては一旦停止して、別のプログラムを実行みたいな事をやってるからです。
また、キーボードやマウスからの入力が無い、アクティブウィンドではない(一番オモテにある窓じゃない、あるいは最小化されている)アプリケーションは、プログラムが動いていても待ち状態で特に計算する事が無い場合があります。
あるいは計算処理をそんなに急いでやらなくても良い場合が多いです。
なのでそういったアクティブではないプログラムが使ってるメモリをいったんHDDに移して、今最優先で処理しなければならないプログラムにメインメモリを使わせる。
そのためにの「仮想メモリ」です。
「仮想メモリ」をメモリの最大値を増やすものと勘違いしている人が多いですが、メモリが増えるのではなく、「同時に起動できるアプリケーションの数」を増やすための仕組みなんです。

また「仮想」メモリですから、動作が非常に遅くなります。
コンピュータはHDDから直接読み出したプログラムをメモリに置かずに実行して、またHDDに記録し直すなんて事はできません。
CPUがアクセスできるのはあくまで「物理メモリ」だけです。
優先度が低いメモリの内容をHDDに書き出して、必要な時にまたメモリに読み直しているのは「チップセット」と呼ばれる外部とのデータのやり取りを制御する別の部品です。
それにHDDはメモリに比べて極端に読み書きのスピードが遅いです。

現在のコンピュータを使ったシステムの中核となるのはデータベースですが、このデータベースというシステムはいちいちHDDが読み出してプログラムにデータを渡して、終わったら更新されたデータをHDDに書き込むなんて事を逐一やってません。
なぜならそんな事をしていたら遅くて使い物にならないからです。
アプリケーションサーバなど計算処理を担当するコンピュータはCPUを高速なものにしたり、複数のCPUを載せたりする事で処理スピードを上げますが、データベースサーバの処理スピードを上げる時は通常はメモリを増やします。

ネットゲームで「巻き戻り」と言われる現象が起きるのも、このデータベースの仕様によるものです。
ネットゲームでは非常に膨大なデータの書き換えが頻繁に行われます。
プレイヤーのHP/MPの値とか、今いるMAPの座標とか、アイテムとかスキルのCD(クールダウン 次にそのスキルを使えるようになるまでの時間)とか、とにかく他の業務システムの比じゃないほどデータの読み出し、書き換えが行われています。
そんなものを、いちいち律儀にHDDから読み込んで書き込んでなんてしていたら、とてもじゃないけどリアルタイムでゲームが動きません。
ラグとかスペック不足でカクカクになるとか、そんなレベルじゃないものになります。
なのでそれらは全てデータベースサーバのメモリ上で行い、一定の間隔で現在の状態をHDDに書き込むのです。
それゆえにサーバがダウンしてしまうと、メモリ上にあった最新データが失われてしまうので、前回書き込んだ時点のデータに戻ってしまうのです。

ウルティマ・オンラインという昔のMMOのサーバプログラムが「神レベル」と言われるのは、今のMMOよりはるかに多くのデータを持ちながら、今のサーバよりはるかに低い性能でラグらずに行えていたからでしょう。
ToSを作った人達は見習って下さいねw
ROの時代からどんだけ開発してるんですか?w
ネクソンさん、あなた方どんだけ昔からネットゲームの運営してるんですか?

カウンタ
プロフィール

ウホッ!いい男

Author:ウホッ!いい男
異世界転生を待ち続ける中高年のおっさん

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR