2012-01-15 59 views
1

如果unicode使用17位碼點,代理點是如何從代碼點計算的?如何計算代理對?

+1

你是什麼意思? Unicode代碼點不是17位,而UTF-8不使用代理對。 – kennytm 2012-01-15 08:36:44

+0

Unicode代碼點需要大約21位。它雖然使用了每個65536碼點的17個平面,總共得到了1114112個碼點。大約20.087位。 – dalle 2012-01-15 08:40:22

回答

7

Unicode代碼點是範圍從0x000000到0x10FFFF的標量值。因此它們是21位整數,而不是17位。

代理對是UTF-16格式的一種機制。這表示21位標量值爲一個或兩個16位代碼單元。

  • 從0x000000到0x00FFFF的標量值表示爲單個16位代碼單元,從0x0000到0xFFFF。
  • 從0x00D800到0x00DFFF的標量值不是Unicode中的字符,因此它們不會出現在Unicode字符串中。
  • 從0x010000到0x10FFFF的標量值表示爲兩個16位代碼單元。第一個編碼單元將標量值的高11位編碼爲從0xD800-0xDBFF範圍內的代碼單元。用四位對0x01-0x10的值進行編碼有一些技巧。第二個編碼單元將標量值的低10位編碼爲範圍從0xDC00-0xDFFF的代碼單元。

這是在Unicode聯合會的常見問題解答UTF-8, UTF-16, UTF-32 & BOM中用示例代碼詳細說明的。該FAQ引用了更詳細的Unicode標準部分。

+1

FAQ中的示例代碼處理將代理對映射到代碼點。問題是關於反向映射;它在Unicode標準的第3章D91中提出,http://www.unicode.org/versions/Unicode6.0.0/ch03.pdf – 2012-01-15 08:59:46

+0

+1很好的答案。 – dalle 2012-01-15 09:00:11

+0

@ JukkaK.Korpela,當我閱讀FAQ條目[問:什麼是從UTF-16轉換爲字符代碼的算法?](http://www.unicode.org/faq//utf_bom.html#utf16-3) ,我看到了示例代碼,用於將字符代碼映射到UTF-16並再次映射,儘管標題不能保證它。 – 2012-01-15 09:12:00

4

如果它是你之後的代碼,下面是單個代碼點分別以UTF-16和UTF-8編碼的方式。

單碼點爲UTF-16 CODEUNITS:

if (cp < 0x10000u) 
{ 
    *out++ = static_cast<uint16_t>(cp); 
} 
else 
{ 
    *out++ = static_cast<uint16_t>(0xd800u + (((cp - 0x10000u) >> 10) & 0x3ffu)); 
    *out++ = static_cast<uint16_t>(0xdc00u + ((cp - 0x10000u) & 0x3ffu)); 
} 

單碼點爲UTF-8 CODEUNITS:

if (cp < 0x80u) 
{ 
    *out++ = static_cast<uint8_t>(cp); 
} 
else if (cp < 0x800u) 
{ 
    *out++ = static_cast<uint8_t>((cp >> 6) & 0x1fu | 0xc0u); 
    *out++ = static_cast<uint8_t>((cp & 0x3fu) | 0x80u); 
} 
else if (cp < 0x10000u) 
{ 
    *out++ = static_cast<uint8_t>((cp >> 12) & 0x0fu | 0xe0u); 
    *out++ = static_cast<uint8_t>(((cp >> 6) & 0x3fu) | 0x80u); 
    *out++ = static_cast<uint8_t>((cp & 0x3fu) | 0x80u); 
} 
else 
{ 
    *out++ = static_cast<uint8_t>((cp >> 18) & 0x07u | 0xf0u); 
    *out++ = static_cast<uint8_t>(((cp >> 12) & 0x3fu) | 0x80u); 
    *out++ = static_cast<uint8_t>(((cp >> 6) & 0x3fu) | 0x80u); 
    *out++ = static_cast<uint8_t>((cp & 0x3fu) | 0x80u); 
}