文字コード地獄秘話 第1話:Unicodeにおける全角・半角

ごあいさつ

皆様はじめまして、文字コードおじさんです。細々とカメラ屋を営んでおりましたが、エンジニアとしての技量を評価され、ALBERTのシステム開発・コンサルティング部で働くことを許されました。特技はサーバーの統廃合です。

今回は最初ということですが、Unicodeにおける全角・半角の取り扱いについて触れてみようと思います。なお、さも連載するかのように第1話と銘打っていますが、上層部の無慈悲な裁決によっては1話打ち切りもありえますので、その際はご容赦ください。

固定観念を捨てよう

「全角50文字、半角100文字まで」といったような文言を見かけたことがあると思います。 特にUnicode以前のレガシーな処理系では全角文字に2バイト、それ以外は1バイトという割り当てが慣習となっていました。 このため、「全角=2バイト文字、半角=1バイト文字」という観念が世間に定着しているのが現状です。

しかし、「文字幅」と「文字に割り当てるバイナリ値」の両者の関係は独立した問題です。 文字コード体系が変われば割り当て方も当然異なってきます。特にUnicodeを扱ううえでは「全角=2バイト文字、半角=1バイト文字」という見方で臨むと

  • あれ?ひらがななのに3バイトある(UTF-8)
  • 半角カナなのになんで2バイトなん?(UTF-16)
  • 「が」が6バイト!?(結合文字列)

と、混乱すること請け合いです。 なのでまずは、「全角だから○○バイトだ!」みたいな考え方は投げ捨てましょう。

Unicodeにおける全角・半角の取り扱い

East Asian Widthとは

さて、UnicodeにおいてはUnicodeコンソーシアムという団体が全角・半角の取り扱いについて、 Unicode Standard Annex #11という附則でEast Asian Width(以下EAW)という値を定めています。 それに従うと、Unicodeの文字は下記の6つに分類されます。

F:Fullwidth

全角に該当する文字。文字の名前に”FULLWIDTH”と付く。

具体例:全角英数など

H:Halfwidth

半角に該当する文字。文字の名前に”HALFWIDTH”と付く。

具体例:半角カナなど

W:Wide

F以外で全角に該当する文字。

具体例:漢字、ひらがな、カタカナなど。

Na:Narrow

H以外で半角に該当し、対応する全角文字が存在する文字。

具体例:半角英数など

A:Ambiguous

曖昧。文脈次第で全角・半角か取扱いが変わる。

具体例:ギリシア文字、キリル文字など

N:Neutral

中立。そもそも東アジア圏に存在しない文字。

具体例:アラビア文字、ヘブライ文字など

厄介なAmbiguous

さて、先に上げた6つの中に文脈次第で取り扱いが変わる不穏な子がいましたね。 実際に見てみましょう。

Ambiguousの一例

OH!この世界はどうなっとるんだぁ!!残酷な仕様で満ち溢れているじゃないか!!私は悲しい。とても悲しい。。。

思わずゲイツ先生の名言を引用してしまいましたが、上記の画像は上がMSゴシック、下がConsolasです。それぞれ等幅フォントでフォントサイズは72ポイントに設定しています。 文字幅がぴったり1:2となっているわけではありませんが、明らかに違う文字幅で描画されていることがわかると思います (カーニングを不正に調整したとか、そういうのじゃないですよ!!)

Ambiguousについては文脈次第で全角・半角の取り扱いが変わると書きました。具体的には東アジアの用字系なら全角、それ以外なら半角という取扱いです。 上記の例ではMSゴシックは東アジアの用字系で使われている和文が扱えるフォントのため全角扱い、 他方Tahomaは欧文フォント=東アジア以外の用字系となるため半角で描画されています。

上の画像に収録した文字列について、念のため文字種とEAWを調べてみると、、

文字列の分析結果その1

全部Ambiguousですね。。。

Amibguousに該当する文字はギリシャ文字やキリル文字のように、もともとは東アジア固有の文字ではないが、東アジアのレガシーな文字コードに含まれていた文字が該当します。 ただし、ギリシャ文字やキリル文字の中には気息記号が付いたものがあります。これらは東アジアで用いられていなかったためNeutralであることがほとんどです。 また、ラテン文字の気息記号付であっても、中国語のピンインで使われていたため、小文字の一部がAmbiguousになっていて、大文字はNeutralだったりするものがあります。

例を見てみましょう。

NaとAが入り乱れた結果

なんかもうひどい面構えですね。文字種とEAWを調べると、、、

文字列の分析結果その2

気息記号がないものはNarrow、あるものはAmbiguousというおぞましいことになりました(白目

結局どうすればいいの?

Unicodeコンソーシアムでは、下記の通り取り扱うよう推奨しています。

東アジアの用字系

  • 全角として扱う:F、W、A
  • 半角として扱う:H、Na、N

東アジア以外の用字系

  • 全角として扱う:F、W
  • 半角として扱う:H、Na、A、N

※厳密にいうと全角は出現しない

まとめ

  • ○○バイト文字だから全角!という固定観念は捨てよう
  • East Asian Widthは6種類あるお(F、H、W、Na、A、N)
  • Amibguousは東アジアなら全角、そうでないなら半角
  • Ураааааааааааа!!

参考文献