シリーズ「コンピュータの文字のしくみ」 第4回

回路が「区切る」とは?

何千もの文字

これまでの話を、短く振り返っておく。

コンピュータの中にあるのは、0 と 1 の並び、パターンだけだ。 8 桁のまとまりを、語と呼ぶ。 どのパターンをどの文字と読むかは、人が決めた表で決まる。この表を文字コードという。 英語圏で決めた ASCII は、128 通りのパターンに、英字・数字・記号を割り当てた(第1回)。

そのパターンから、光る形を作ることもできた。 数字なら 7 本の棒で(第2回)、どんな文字でも点の並びで(第3回)。

けれど、駅の掲示板には、漢字も出る。 第1回の終わりには、「128 通りでは、とても足りない」と書いた。 前回は、こう締めくくった。

8 桁の語で、何千もの文字を、どう表すのか。

まず、何千もの「何千」を確かめておこう。 日本の文字の表は、国の規格(JIS X 0208)で決まっている。 はじめの版は 1978 年。 いまの版には、漢字が 6355 字、ひらがな・カタカナ・記号などを合わせると 6879 文字が入っている。

8 桁のパターンは、2 を 8 回かけて、28 = 256 通りだ。 6879 文字には、とても足りない。

1 語で足りないなら、2 語を組にして、1 文字にすればいい。 2 語なら 16 桁。2 を 16 回かけて、216 = 65536 通りある。 6879 文字が、楽に入る。

話は、これで終わりそうに見える。 ところが、ここから困ったことが起きる。 この回は、その話をする。

16 進で、書く

その前に、書き方を 1 つ決めておく。

2 語は 16 桁だ。 1000 1001 0111 0111 と書かれても、目で追うのが大変だ。

そこで、4 桁ずつ区切って、1 字で書くことにする。 4 桁のパターンは、0000 から 1111 までの 16 通り。 数として読めば 0 から 15 だ。 0 から 9 はそのまま数字で、10 から 15 には、A・B・C・D・E・F を当てる。

00000
10001
20010
30011
40100
50101
60110
70111
81000
91001
A1010
B1011
C1100
D1101
E1110
F1111
4 桁のパターンを、1 字で。A〜F も 7 本の棒で書ける(b と d は小文字)

16 通りの字で書くので、この書き方を 16 進という。

第2回の 7 本の棒の回路では、1010 から 1111 を入れても、何も光らせなかった。 16 進では、そこに A から F が入る。 7 本の棒でも、b と d を小文字にすれば、6 つとも書ける。

16 進で書いてみよう。 1000 1001 は、前の 4 桁 1000 が 8、後ろの 4 桁 1001 が 9 なので、89。 第1回の「A」の 0100 0001 は、41 になる。

ひとつ、気をつけてほしい。 16 進の 89 は、八十九ではない。 前の字が 16 が何個か、後ろの字が 1 が何個かを表すので、10 進に直すと 8 × 16 + 9 = 137 だ。 混ざらないように、この回では、16 進を 89 のような字で書く。

2 語で、1 文字

日本のパソコンで長く使われてきた約束に、Shift_JIS(シフト・ジス)がある。

Shift_JIS では、「駅」は 89 77 の 2 語だ。

国の表の席
17 区 56 点
Shift_JIS では
89 77
1000 1001
0111 0111
第3回の「駅」。席の番号を、2 語で書く

国の表は、文字を、縦 94・横 94 のマス目に並べている。 文字の場所は、「何区の何点」という席の番号で呼ぶ。 「駅」の席は、17 区 56 点だ。

第3回の最後に描いた「駅」の形も、実は、国の別の規格(JIS X 9051)が決めた、同じ 17 区 56 点の形だった。 文字の形の表も、同じ席の番号で並んでいる。

Shift_JIS は、この席の番号を、2 語に書き直す約束の 1 つだ。 同じ席の番号を、別のやり方で 2 語にする約束もある(EUC-JP や、メールでよく使われた JIS)。 この回は、Shift_JIS だけを見る。

ほかの文字も、2 語ずつだ。

文字Shift_JIS
あ82 A0
漢8A BF
字8E 9A
駅89 77

ただし、全部の文字が 2 語になったわけではない。

英字や数字は、ASCII のまま 1 語だ。「A」は 41。 それに、日本のコンピュータには、もっと前から、カタカナを 1 語で書く表があった(JIS X 0201)。 半分の幅で書く小さなカタカナなので、半角カナと呼ぶ。「ア」は B1 の 1 語だ。 古い機械との行き来のために、Shift_JIS は、この 1 語の文字も残した。

だから、「Aアあ駅」は、こう並ぶ。

41 B1 82 A0 89 77

区切って書いたので、読める。 けれど、届くのは区切りの無い語の並びだ。

41 B1 82 A0 89 77

ここで、最後の 77 を見てほしい。 2 進で 0111 0111。いちばん上の桁が 0 だ。 1 語として ASCII で読むと、これは「w」である。

89 77 は「駅」の 1 文字なのか。それとも、何かの 1 文字と「w」なのか。 語の並びのどこからどこまでが 1 文字なのか。 この切れ目を、区切りと呼ぶことにしよう。

区切りを知らなければ、正しく読めない。

どこで、区切るか

Shift_JIS の答えは、こうだ。

1 語目を見る。 1 語目が 81 から 9F まで、または E0 から FC までなら、その語と次の語で 1 文字。 それ以外なら、その語だけで 1 文字。

「駅」の 89 は 81 から 9F のあいだなので、次の 77 とあわせて 1 文字になる。 「A」の 41 や「ア」の B1 は、どちらにも入らないので、1 語で 1 文字だ。

この 81〜9F と E0〜FC を、この回では 1 語目の範囲、短く「範囲」と呼ぶ。 2 語の始まりになれるパターンの範囲、という意味だ。

範囲が飛び飛びなのには、わけがある。 00 から 7F は ASCII、A1 から DF は半角カナが、もう使っていた。 2 語の始まりは、そこをよけて、空いているところへずらして置いたのだ。 名前の Shift(ずらす)は、ここから来ている、と言われる。

この約束は、1980 年代のはじめに、日本のパソコンのために、アスキーやマイクロソフトなどの会社が作った。 のちに、国の規格(JIS X 0208 の 1997 年の版)にも入った。

範囲を、2 進で見てみよう。 語の上 3 桁で分けると、きれいに分かれる。

上 3 桁16 進読み方
0で始まる00〜7FASCII(1 語)
10080〜9F2 語の始まり
101・110A0〜DF半角カナ(1 語)
111E0〜FF2 語の始まり

上 3 桁が 100 か 111 なら、2 語の始まり。 言いかえると、「いちばん上の桁が 1、しかも 2 桁目と 3 桁目が同じ」だ。

2 桁目と 3 桁目が同じかどうかは、XOR で分かる。 第1回で見たとおり、XOR は、2 つの入口が食い違っているときだけ 1 を返す。 その反対(NOT)が、「同じ」だ。 それと、いちばん上の桁を AND でまとめれば、できあがる。

1 語目の範囲か シミュレータ

上 3 桁のスイッチを押して、どのときにランプが点くか確かめてください

XORNOTAND上から 1 桁目12 桁目03 桁目02 語の始まり

上 3 桁が 100 の語は 80〜9F

2 語の始まり

上の桁から 1・0・0 のときと、1・1・1 のときだけ、ランプが点く。 ゲートは 3 個。下の 5 桁は、見てもいない。

正確に言うと、この回路は、80 と、FD・FE・FF も「2 語の始まり」にしてしまう。 けれど、この 4 つのパターンは、文字には使っていない(半角カナの手前の A0 も同じ)。 また、国の規格の本文では、範囲は E0 から EF までだ。 F0 から FC は、使う人が自分で文字を足すための場所としてあけてあり、多くのパソコンはそこまで使っている。

さて、これで区切れるだろうか。

実は、まだ足りない。 2 語目のほうは、40 から 7E と、80 から FC までのパターンを使う。 「駅」の 77 のように ASCII と同じパターンもあれば、1 語目の範囲の中のパターンもある。 つまり、2 語目なのに、1 語目にも見えてしまうパターンだ。

たとえば、「東京駅」はこう並ぶ。

93 8C 8B 9E 89 77

最後の 77 以外は、どれも 1 語目の範囲の中だ。 8C も 9E も、本当は 2 語目なのに。 語を 1 つずつ見て「範囲か」を決めるだけでは、8C が「東」の 2 語目なのか、新しい文字の 1 語目なのか、分からない。

だから、前から順に読む。

  1. いちばん前の語は、文字の始まり(文字の頭)だ。
  2. 文字の頭の語が範囲の中なら、次の語は、その文字の 2 語目。
  3. 2 語目の次の語は、範囲かどうかに関係なく、また文字の頭。

「次の語は頭か」を、前の語から 1 つずつ渡していけばいい。 回路にすると、語ごとに、こうなる。

  • 「この語が頭」AND「この語が範囲」 = 次の語は 2 語目
  • それを NOT で反転したもの = 次の語は頭

『計算のしくみ』を読んだ人は、第2回の全加算器を思い出してほしい。繰り上がりを下の桁から隣の桁へ渡していくのと同じように、ここでは「次の語は頭か」を、前の語から隣の語へ渡していく。

押して、確かめる

6 つの語を、上から下へ並べた。 語ごとに「範囲か」の回路があり、「頭か」を上から下へ渡していく。

Shift_JIS の区切り シミュレータ

語を押して、下のマスでパターンを替えてみてください

語範囲か頭か文字Aアあ駅0410100 0001範囲か上 3 桁読み始め ▶ANDNOT1B11011 0001範囲か上 3 桁ANDNOT2821000 0010範囲か上 3 桁ANDNOT3A01010 0000範囲か上 3 桁ANDNOT4891000 1001範囲か上 3 桁ANDNOT5770111 0111範囲か上 3 桁AND

黄色の丸 = この語から文字が始まる。AND = 頭で、しかも範囲なら、次の語は 2 語目

読んだ文字:Aアあ駅(「Aアあ駅」の並び)

0 番の語 41(枠の 3 桁が「範囲か」を見る桁)
例:

左のマスが語だ。大きな字が 16 進、その下が 2 進の 8 桁で、「範囲か」が見る上 3 桁は琥珀色にしてある。 語は、いちばん上を 0 番として数える。

はじめは「Aアあ駅」の 41 B1 82 A0 89 77 だ。上から追ってみよう。

  • 0 番の 41 は、読み始めの語なので、頭(黄色の丸が光っている)。上 3 桁は 010 で、範囲ではない。AND は 0。NOT で反転して、1 番を頭にする。右の枠には「A」。
  • 1 番の B1 も頭。上 3 桁は 101、半角カナなので範囲ではない。2 番も頭になる。「ア」。
  • 2 番の 82 は頭で、上 3 桁が 100。範囲だ。AND が 1 になり、NOT で反転して、3 番は頭ではなくなる。
  • 3 番の A0 は、上 3 桁が 101。けれど頭ではないので、AND は 0。2 番と 3 番で「あ」。4 番は頭になる。
  • 4 番の 89 は頭で、範囲。5 番の 77 とあわせて「駅」。

右の枠と、左の語のマスに敷いた黄色い枠が、区切った 1 文字だ。 枠と枠のあいだが、区切りである。

次は、例の「東京駅」を押してみてほしい。 「範囲か」は、最後の 5 番以外、全部が緑になる。 それでも、黄色の丸は 1 つおきに光り、「東」「京」「駅」と正しく区切れる。 「範囲か」だけでは決まらず、前の語から渡ってくる「頭か」があって、はじめて決まるのだ。

「12番線」も試してみよう。 31 と 32 は ASCII の数字なので 1 語ずつ、94 D4 と 90 FC は 2 語ずつ。 1 語の文字と 2 語の文字が混ざっていても、区切りは前から順に決まっていく。

語のマスを押せば、下の 8 つのマスで、その語のパターンを替えられる。 上 3 桁を替えると、そこから下の区切りが、まとめて替わるはずだ。

2 語で 1 文字にすると、どこで区切るかが問題になる。Shift_JIS は、1 語目のパターンを見て、それが 2 語の始まりかどうかを決める。

この回路は、「駅」を知らない。 上 3 桁を見て、前から渡ってきた「頭か」と AND を取り、反転して次へ渡す。それだけだ。

正直に書いておくと、右の枠の文字は、区切った語を、ブラウザが持っている Shift_JIS の表で引いて出している。 区切りを決めるところは本物のゲートだが、7000 文字近い表をゲートで組むのは、さすがに大きすぎる。 作り方は、第3回の文字の形のメモリと同じで、表が大きくなるだけだ。

部品を数えておこう。 「範囲か」が XOR・NOT・AND の 3 個ずつで 18 個、頭を渡す AND が 6 個と NOT が 5 個。あわせて 29 個だ。

ダメ文字

区切りを知らない読み手は、どうなるか。 困った例が、昔から知られている。

「表」は、Shift_JIS で 95 5C だ。

2 語目の 5C は、2 進で 0101 1100。いちばん上の桁が 0 なので、1 語として読めば ASCII の文字になる。 ASCII の 5C は「\」(バックスラッシュ)。 日本の半角の表(JIS X 0201)では、同じ 5C に「¥」(円の記号)が当ててあるので、日本のパソコンでは「¥」と表示されることが多い。

コンピュータのプログラムの中には、この「\」を、特別な意味の印として使うものが多い。 たとえば「\n」で改行を表す、といった使い方だ。

区切りを考えずに、語を 1 つずつ見ていくプログラムは、「表」の 2 語目の 5C を、この印と取り違える。 すると、「表」の 1 語目だけが取り残されたり、次の文字と組にされたりして、文字が壊れる。

2 語目が 5C の文字は、ほかにもある。

文字Shift_JIS
表95 5C
ソ83 5C
能94 5C

プログラムを書く人たちのあいだでは、こうした文字を ダメ文字 と呼んできた。 文字が悪いのではない。区切りを知らずに読むほうが悪いのだ。

上のシミュレータで、例の「表示板」を押してみてほしい。 区切りを知っている回路は、95 5C をちゃんと「表」と読む。

途中から、読んだら

もう 1 つ、困ることがある。

ここまでは、いつも、いちばん前の語から読んでいた。 では、途中の語から読み始めたらどうなるか。 長い文章の途中だけを取り出したときや、前のほうが届かなかったときに、そういうことが起きる。

さっきの回路の、読み始める語を替えられるようにした。 はじめは「東京駅」を、1 番の語から読んでいる。

途中から読む シミュレータ

読み始める語を替えて、区切りがどう変わるか見てください

語範囲か頭か文字結梔w読まない0931001 0011範囲か上 3 桁18C1000 1100範囲か上 3 桁読み始め ▶ANDNOT28B1000 1011範囲か上 3 桁ANDNOT39E1001 1110範囲か上 3 桁ANDNOT4891000 1001範囲か上 3 桁ANDNOT5770111 0111範囲か上 3 桁AND

黄色の丸 = この語から文字が始まる。AND = 頭で、しかも範囲なら、次の語は 2 語目

読んだ文字:結梔w

0 番の語 93(枠の 3 桁が「範囲か」を見る桁)
例:
読み始める語:

1 番の 8C は、本当は「東」の 2 語目だ。 けれど、読み始めの語なので、頭として扱われる。 8C は範囲の中なので、8C 8B で 1 文字。続く 9E 89 で 1 文字。最後の 77 で 1 文字。

出てきたのは、「結梔w」。

1 語ずつずれたまま、最後までずれている。 どの語も範囲の中なので、ずれを取り戻すきっかけが無い。 しかも、出てきた「結」や「梔」は、どれも表にある、ちゃんとした文字だ。読み手は、取り違えたことにさえ気づけない。

読み始めを 2 番にすると、「京駅」と正しく読める。2 番は、たまたま本当の頭だったからだ。

例の「品川駅」を、1 番から読んでみてほしい。 今度は「i川駅」になる。 69 は範囲の外なので、ここで 1 語の文字(ASCII の「i」)として区切られ、次からは正しい区切りに戻る。 戻れるかどうかは、並びしだいだ。

Shift_JIS では、途中の語を見ただけでは、そこが文字の頭なのかどうか分からない。 確かめるには、いちばん前まで戻って、数え直すしかない。

ここまでは、それでも、読む側が Shift_JIS の約束を知っていた。

けれど、日本の中だけでも、2 語の約束は Shift_JIS・EUC-JP・JIS と 3 つある。 海の向こうでは、中国も韓国も、それぞれ自分の文字の表と、2 語の約束を作った。 同じ語の並びが、約束によって、まったく違う文字になる。

約束を知らない人が読むと、何が起きるか。

参考文献

シリーズ「コンピュータの文字のしくみ」