UnicodeとUTF-8の変換式
(2021年9月28日)
UnicodeとUTF-8の変換式
u = ¹v₆×2⁶[n=0] + ⁶⁻ⁿv₈ₙ×2⁶ⁿ + (⁶v₀+⁶v₈×2⁶+…+⁶v₈ₙ₋₈×2⁶ⁿ⁻⁶)
を導出します。
ここで,uはUnicode,vはUTF-8,n=[(log₂u-1)/5][2⁷≦u]=[log₂v/8]はUTF-8のバイト数-1,ⁱwₙ=[w/2ⁿ]%2ⁱはw=u,vの第n+1~n+iビット,%は剰余,[ ]は数値の整数部分,または,真なら1偽なら0(アイバーソンの記法)。
ただし,vからuを計算する式(第二式)は,UTF-8でないコードに対しても値を計算します。例えば,v=0xD7A68FはUTF-8でないコードですが,この式はu=0x798Fと計算してしまいます。vがUTF-8の必要条件を満たすか否かは,以下の不等式で判定できます(カンマはAND):
UTF-8 v = = 0x
(導出)
UTF-8では,Unicodeを次のように1~4バイトで表します:
- 1バイトコードは先頭ビットが0(0x0~7)
- 2バイトコードは先頭ビットが110(0xC~D)
- 3バイトコードは先頭ビットが1110(0xE)
- 4バイトコードは先頭ビットが1111 0(0xF0~F7)
- n>1バイトコードの2バイト目以降は10(0x8~B)
それゆえ,
- 1バイトコードは7ビットでUnicodeの0から2⁷-1=127(0x7F),
- 2バイトコードは11ビットでUnicodeの128から2¹¹-1=2047(0x7FF),
- 3バイトコードは16ビットでUnicodeの2048から2¹⁶-1=65535(0xFFFF),
- 4バイトコードは21ビットでUnicodeの65536から2²¹-1=2097151(0x1FFFFF)
を表します。
これより,UTF-8は,uの第n+1~n+iビットをとりだした値ⁱuₙ=[u/2ⁿ]%2ⁱを用いて,
- 2⁷≦u<2¹¹に対しては,
(2⁷+2⁶+⁵u₆)×2⁸ + (2⁷+⁶u₀)
- 2¹¹≦u<2¹⁶に対しては,
(2⁷+2⁶+2⁵+⁴u₁₂)×2¹⁶ + (2⁷+⁶u₆)×2⁸ + (2⁷+⁶u₀)
- 2¹⁶≦u<2²¹に対しては,
(2⁷+2⁶+2⁵+2⁴+³u₁₈)×2²⁴ + (2⁷+⁶u₁₂)×2¹⁶ + (2⁷+⁶u₆)×2⁸ + (2⁷+⁶u₀)
したがって,3つの場合をまとめて,2⁷≦u<2²¹に対して,n=[(log₂u-1)/5]-[2⁶≦u][u<2⁷]をUTF-8のバイト数-1として,
v = (2⁶+…+2⁷⁻ⁿ)×2⁸ⁿ+(2⁷+⁶u₀)+(2⁷+⁶u₆)×2⁸+…+(2⁷+⁶u₆ₙ)×2⁸ⁿ
2⁶+…+2⁷⁻ⁿ=(2ⁿ-1)×2⁷ⁿ⁺⁷, n≧1より,
= (2ⁿ-1)×2⁷ⁿ⁺⁷+(2⁷+⁶u₀)+(2⁷+⁶u₆)×2⁸+…+(2⁷+⁶u₆ₙ)×2⁸ⁿ.
ここで,0<u<2⁷,すなわち,n=0の時,この式は
2⁷+⁶u₀ = 2⁷+u-¹u₆×2⁶=u+2⁶(2-¹u₆)
なので,0<u<2²¹に対して,
v = (2ⁿ-1)×2⁷ⁿ⁺⁷-2⁶(2-¹u₆)[n=0] + (2⁷+⁶u₀)+(2⁷+⁶u₆)×2⁸+…+(2⁷+⁶u₆ₙ)×2⁸ⁿ
逆に,Unicodeは,vの第n+1~n+iビットをとりだした値ⁱvₙ=[v/2ⁿ]%2ⁱを用いて,
- n=1に対しては,
⁵v₈×2⁶ + ⁶v₀
- n=2に対しては,
⁴v₁₆×2¹² + ⁶v₈×2⁶ + ⁶v₀
- n=3に対しては,
³v₂₄×2¹⁸ + ⁶v₁₆×2¹² + ⁶v₈×2⁶ + ⁶v₀
となります。ここで,n=[log₂v/8]はUTF-8のバイト数-1。
したがって,3つの場合をまとめて,n>0に対して,
u = (⁶v₀+⁶v₈×2⁶+…+⁶v₈ₙ₋₈×2⁶ⁿ⁻⁶) + ⁶⁻ⁿv₈ₙ×2⁶ⁿ
ここで,n=0,すなわち,0<v<2⁷の時,この式は(カッコ内の級数は生じないと解釈して)
⁶v₀ = v - ¹v₆×2⁶
なので,0<v<2²¹に対して,
u = ¹v₆×2⁶[n=0] + ⁶⁻ⁿv₈ₙ×2⁶ⁿ + (⁶v₀+⁶v₈×2⁶+…+⁶v₈ₙ₋₈×2⁶ⁿ⁻⁶)
最後に,vがUTF-8の必要条件を満足しているかどうかの判定。
- n=0に対しては,先頭ビットが0,すなわち,v<2⁷
- n=1に対しては,先頭ビットが110,2バイト目以降は10,かつ,u≧2⁷,すなわち,
2⁷+2⁶≤⁸v₈<2⁷+2⁶+2⁵,2⁷≤⁸v₀<2⁷+2⁶,2¹⁵+2¹⁴+2⁷ +2⁷⁺²≤v - n=2に対しては,先頭ビットが1110,2バイト目以降は10,かつ,u≧2¹¹,すなわち,2⁷+2⁶+2⁵≤⁸v₁₆<2⁷+2⁶+2⁵+2⁴,2⁷≤⁸v₈<2⁷+2⁶,2⁷≤⁸v₀<2⁷+2⁶,2²³+2²²+2²¹+2¹⁵+2⁷ +2¹¹⁺²≤v
- n=3に対しては,先頭ビットが11110,2バイト目以降は10,かつ,u≧2¹⁶,すなわち,2⁷+2⁶+2⁵+2⁴≤⁸v₂₄<2⁷+2⁶+2⁵+2⁴+2³,2⁷≤⁸v₁₆<2⁷+2⁶,2⁷≤⁸v₈<2⁷+2⁶,2⁷≤⁸v₀<2⁷+2⁶,2³¹+2³⁰+2²⁹+2²⁸+2²³+2¹⁵+2⁷ +2¹⁶⁺²⁺²≤v
まとめて,0<n<4に対して,
0≤⁸v₈ₙ-(2⁷⁻ⁿ+…+2⁷)<2⁶⁻ⁿ,0≤⁸v₀-2⁷<2⁶,…, 0≤⁸v₈ₙ-₈-2⁷<2⁶,(2⁷⁻ⁿ+…+2⁷)2⁸ⁿ+(2⁰+…+2⁸ⁿ⁻⁸)2⁷+2⁹[n=1]+2¹³[n=2]+2²⁰[n=3]≤v
2⁷⁻ⁿ+…+2⁷=2⁸-2⁷⁻ⁿなので,
0≤⁸v₈ₙ-2⁸+2⁷⁻ⁿ<2⁶⁻ⁿ,0≤⁸v₈ₖ-2⁷<2⁶ for k=0,...,n-1,0xC280[n=1] + 0xE0A080[n=2] + 0xF0908080[n=3]≤v
Q.E.D.
コメント
コメントを投稿