16ビット(2バイト)あれば 216=65536 文字を登録できます。漢字を知っている人ならすぐに足りないと感じますが、最初はこれで全世界の文字を登録できると思っていた様です。
当然不足して、32ビット(4バイト)にする案もあったのですが、いろいろあって結局 21ビット(3バイトより少ない)に落ち着きました。 0~10FFFF です。
16進の1桁は4ビットですから、5桁で20ビット、それに1ビットを足して21ビットです。21ビットで表せる文字数は、221=2097152 ですが、それは 1FFFFF まで使う場合です。実際には 10FFFF までですので 1114112 文字になります。
第0面から第16面までの17面が使えて、1面は16ビットですから、216×17=1114112 です。
Unicodeスカラ値の範囲 | 文字 | 説明 |
---|---|---|
0000〜 FFFF | 第0面 | 基本多言語面(BMP) |
10000〜 1FFFF | 第1面 | 追加多言語面(SMP) |
20000〜 2FFFF | 第2面 | 追加漢字面(SIP) |
30000〜 3FFFF | 第3面 | 第3漢字面(未使用)(TIP) |
40000〜 4FFFF | 第4面 | 未使用・用途未定 |
50000〜 5FFFF | 第5面 | 未使用・用途未定 |
60000〜 6FFFF | 第6面 | 未使用・用途未定 |
70000〜 7FFFF | 第7面 | 未使用・用途未定 |
80000〜 8FFFF | 第8面 | 未使用・用途未定 |
90000〜 9FFFF | 第9面 | 未使用・用途未定 |
A0000〜 AFFFF | 第10面 | 未使用・用途未定 |
B0000〜 BFFFF | 第11面 | 未使用・用途未定 |
C0000〜 CFFFF | 第12面 | 未使用・用途未定 |
D0000〜 DFFFF | 第13面 | 未使用・用途未定 |
E0000〜 EFFFF | 第14面 | 追加特殊用途面(SSP) |
F0000〜 FFFFF | 第15面 | 私用面 |
100000〜10FFFF | 第16面 | 私用面 |
文字セットは16進数にU+をつけて U+0000~U+10FFFF で表します。これをUnicodeスカラ値といいます。
第0面は16進数で4桁で U+0000~U+FFFF と表します。この16ビット(2バイト)で表現できる部分は65536文字で、ここには基本的な文字を登録してあり、基本多言語面(BMP)と呼ばれます。
BMPの他に16ビット65536文字の面が16あります。0000~FFFF の前に 1,2,3,...D,E,F,10 と 16進数で 1から16 の番号がついていると考えれば理解できると思います。
JISで面区点で示された文字を実際に使うときに、ISO-2022-JP,Shift_JIS,EUC-JPなどさまざまなエンコーディングを使用したのと同様に、Unicodeにもたくさんの方式があります。主に使われているのは UTF-8 と UTF-16 の2つです。
Unicodeスカラ値の第0面(基本多言語面)は、ほとんどそのままUTF-16の文字コード(2バイト=16ビット)になります。
𠀋(じょう)など第0面にない漢字は、サロゲートペアで表します。予約してある2048個のコードを2つ組み合わせて4バイト=32ビットにして表示する仕組みです。
Unicodeスカラ値 | 文字 | UTF-16 | 説明 |
---|---|---|---|
U+0041 | A | 0041 | スカラ値がそのまま文字コードになる文字 |
U+0061 | a | 0061 | |
U+00E8 | è | 00E8 | |
U+042F | Я | 042F | |
U+2162 | Ⅲ | 2162 | |
U+3042 | あ | 3042 | |
U+4E9C | 亜 | 4E9C | |
U+D558 | 하 | D558 | |
U+2000B | 𠀋(じょう) | D840 DC0B | サロゲートペアを使う文字 |
U+20BB7 | 𠮷(よし) | D842 DFB7 | |
U+29E3D | 𩸽(ほっけ) | D867 DE3D |
Unicodeスカラ値の第0面が、ほとんどそのままUTF-16のコードになります。下の表の文字の配置表はそのままUnicodeスカラ値の第0面の配置表でもあります。
上位代用と下位代用の部分は文字が直接割り当てられていません。上位代用の2バイトと下位代用の2バイトを組み合わせて第1面から第16面までの文字を表します。これをサロゲートペア(代用対)といいます。
UTF-16の範囲 | x000〜x3FF | x400〜x7FF | x800〜xBFF | xC00〜xFFF |
---|---|---|---|---|
0000〜0FFF | ASCII,ラテン拡張AB,ギリシア,キリル,アラビア,タイ | |||
1000〜1FFF | ミャンマー,ハングル字母,クメール,モンゴル | |||
2000〜2FFF | 一般句読点,通貨記号,矢印,数学記号,技術用記号,ラテン拡張C | |||
3000〜3FFF | CJKの記号,平仮名,片仮名,CJK統合漢字拡張A | |||
4000〜4FFF | CJK統合漢字拡張A, CJK統合漢字 | |||
5000〜5FFF | CJK統合漢字 | |||
6000〜6FFF | CJK統合漢字 | |||
7000〜7FFF | CJK統合漢字 | |||
8000〜8FFF | CJK統合漢字 | |||
9000〜9FFF | CJK統合漢字 | |||
A000〜AFFF | キリル拡張,ラテン拡張D,パスパ,ジャワ,ハングル | |||
B000〜BFFF | ハングル | |||
C000〜CFFF | ハングル | |||
D000〜DFFF | ハングル | 上位代用 | 下位代用 | |
E000〜EFFF | 私用領域 (外字領域) | |||
F000〜FFFF | 私用領域 (外字領域),CJK互換漢字,特殊用途文字 |
サロゲートペアの上位は U+D800〜U+DBFF, 下位は U+DC00〜U+DFFF で、それぞれ1024字分あります。組み合わせると 1024×1024=1048576文字になります。これで第1面から第16面までの文字 65536×16=1048576文字を表すことができます。
第1面から第16面のユニコードスカラ値を$unicodeとするとサロゲートペアの上位と下位はそれぞれ次のように計算します。
ただし0xは16進数であることを表し、/は切り捨てをする割り算、%は割り算のあまりを求める計算です。
上位 = ($unicode - 0x10000) / 0x400 + 0xD800; 下位 = ($unicode - 0x10000) % 0x400 + 0xDC00;
元に戻すには
$unicode = 0x10000 + (上位 - 0xD800) * 0x400 + (下位 - 0xDC00);
UTF-16 はもともと全部の文字を2バイトで表現できると思っていたときの方式です。Unicodeスカラ値の16進数4桁(2バイト)をそのまま使っていました。
しかし、これでは不足だと分かってから、まだ文字を登録していなかった 0xD800〜0xDFFF の2048文字分の領域に直接文字を割り付けずに、前半の0xD800〜0xDBFFから1文字分、後半0xDC00〜0xDFFFから1文字分のコードを組み合わせて2文字分つまり4バイトで1文字ということにしました。
これにより2048文字分だった範囲を使って 1024×1024=1048576 文字分を生み出したことになります。
16ビットで表せる文字数 | 216 | 65536 |
サロゲートペアの部分には直接文字を割りつけない | 1024+1024 | -2048 |
サロゲートペアで登録できる文字数 | 1024×1024 | 1048576 |
UTF-16で表せる文字数の合計 | 1112064 |
UTF-8は1~4バイト(初期の定義では6バイトまであった)の可変長コードです。
Unicodeスカラ値 | 文字 | UTF-8 | 説明 |
---|---|---|---|
U+0041 | A | 41 | 1バイト |
U+0061 | a | 61 | |
U+00E8 | è | C3 A8 | 2バイト |
U+042F | Я | D0 AF | |
U+2162 | Ⅲ | E2 85 A2 | 3バイト |
U+3042 | あ | E3 81 82 | |
U+4E9C | 亜 | E4 BA 9C | |
U+D558 | 하 | ED 95 98 | |
U+2000B | 𠀋(じょう) | F0 A0 80 8B | 4バイト |
U+20BB7 | 𠮷(よし) | F0 A0 AE B7 | |
U+29E3D | 𩸽(ほっけ) | F0 A9 B8 BD |
それぞれの1バイトの値で、それが文字の最初のバイトであるか、2バイト目以降のバイトであるかがわかるようになっています。
コード | カテゴリ | 備考 |
---|---|---|
00-7x | 1バイト文字 | US-ASCIIにおなじ |
8x,9x,Ax,Bx | 多バイト文字の2バイト目以降 | |
Cx,Dx | 2バイト文字の開始バイト | |
Ex | 3バイト文字の開始バイト | 漢字はおおむねこれで開始 |
Fx | 4バイト以上の文字の開始バイト | F0-F7は4バイト、(F8-FBは5バイト、FC-FDは6バイト) |
U+XXXX と表されるUnicodeスカラ値からUTF-8への換算方法です。もちろん逆も可能。
ビットの状態にしてから切り貼りをしています。
Unicodeスカラ値 | 二進表現 | UTF-8 の二進表現 | |
---|---|---|---|
(1) | U+ 00 7Fまで | 0000 0000 0ppp pppp | 0ppp pppp |
(2) | U+ 07 FFまで | 0000 0sss pppp pppp | 110s sspp 10pp pppp |
(3) | U+ FF FFまで | ssss ssss pppp pppp | 1110 ssss 10ss sspp 10pp pppp |
(4) | U+ F FF FFまで | tttt ssss ssss pppp pppp | 1111 00tt 10tt ssss 10ss sspp 10pp pppp |
(4') | U+ 10 FF FFまで | 1 0000 ssss ssss pppp pppp | 1111 0100 1000 ssss 10ss sspp 10pp pppp |
(3)の領域から2つ、(4)から1つ例をあげます。
文字 : 聖 スカラー値: U+8056 : 8 0 5 6 二進にして: 1000 0000 0101 0110 並べかえて: 1110 1000 1000 0001 1001 0110 16進にして: E 8 8 1 9 6 UTF-8 : E8 81 96
文字 : 愛 スカラー値: U+611B : 6 1 1 B 二進にして: 0110 0001 0001 1011 並べかえて: 1110 0110 1000 0100 1001 1011 16進にして: E 6 8 4 9 B UTF-8 : E6 84 9B
文字 : 𡈽 スカラー値: U+2123D : 2 1 2 3 D 二進にして: 0010 0001 0010 0011 1101 並べかえて: 1111 0000 1010 0001 1000 1000 1011 1101 16進にして: F 0 A 1 8 8 B D UTF-8 : F0 A1 88 BD
ちなみに、UTF-8に上記の方法で換算するときは、必ずUnicodeスカラ値から換算します。サロケートペアから換算してはいけません。
Unicodeスカラ値 | 文字 | 説明 | UTF-8 | UTF-16 |
---|---|---|---|---|
U+0041 | A | ラテン文字 | 41 | 0041 |
U+0061 | a | ラテン文字 | 61 | 0061 |
U+00E8 | è | ラテン文字 | C3 A8 | 00E8 |
U+042F | Я | キリル文字(ロシア) | D0 AF | 042F |
U+05D0 | א | ヘブライ文字 | D7 90 | 05D0 |
U+0905 | अ | デーヴァナーガリ文字 | E0 A4 85 | 0905 |
U+0E04 | ค | タイ文字 | E0 B8 84 | 0E04 |
U+2162 | Ⅲ | ローマ数字 | E2 85 A2 | 2162 |
U+3042 | あ | ひらがな | E3 81 82 | 3042 |
U+4E9C | 亜 | 漢字(あ) | E4 BA 9C | 4E9C |
U+D558 | 하 | ハングル | ED 95 98 | D558 |
U+103A0 | 𐎠 | 楔形文字 | F0 90 8E A0 | D800 DFA0 |
U+2000B | 𠀋 | 漢字(じょう) | F0 A0 80 8B | D840 DC0B |
U+20BB7 | 𠮷 | 漢字(よし) | F0 A0 AE B7 | D842 DFB7 |
U+29E3D | 𩸽 | 漢字(ほっけ) | F0 A9 B8 BD | D867 DE3D |