文字コード への返答

投稿で使用できる特殊コードの説明。(別タブで開きます。)
本名は入力しないようにしましょう。
投稿した後で削除するときに使うパスワードです。返答があった後は削除できません。
返答する人が目安にします。相手が小学生か社会人かで返答の仕方も変わります。
最初の投稿が質問の場合、質問者が解決時にチェックしてください。(以降も追加書き込み・返信は可能です。)
※「過去ログ」について書くときはその過去ログのURLも書いてください。

以下の返答は逆順(新しい順)に並んでいます。

投稿者 まこ  (社会人) 投稿日時 2021/9/6 19:14:15
魔界の仮面弁士様、ありがとうございます。

非常に濃い内容をご教示頂き、感謝します。

サロゲートペアについては、理解できたつもりです。今まではエンコードに関係なく
U+29E3D 「𩸽」はサロゲート文字という認識だったのです。
今回の件でUTF-16の時のみにサロゲートペアという2バイトのペアを使って表現するという事がわかりました。

異体字については、存在自体は存じておりましたが、関わる事案がなかったので深く調査したことはありませんが
これを機に少し調べようと思います。サロゲートと同じような仕組みで実装されているのですね。

内容が広域なので、全て理解できたとは言えませんが、少しずつ勉強していきたいと思います。
とりあえず、今回の件はこれで解決とさせていただきます。

本当に、ありがとうございました。感謝....
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2021/9/6 14:03:05
サロゲートペアの変換ルールについて、まずは下記 URL の記事を読んでみてください。
2003 年当時(Unicode 3.2.0 ~ 4.0.0 頃)の資料ですが、比較的わかりやすいかと思います。
🔹 http://nomenclator.la.coocan.jp/unicode/ucs_utf.htm


変換ルールは上記の URL を見ていただくとして、U+29E3D 「𩸽」は 
 UTF-32LE では 3D 9E 02 00 の 4 バイト
 UTF-32BE では 00 02 9E 3D の 4 バイト
 UTF-16LE では 67 D8 3D DE の 4 バイト ※サロゲートペア:U+D867,U+DE3E
 UTF-16BE では D8 67 DE 3D の 4 バイト ※サロゲートペア:U+D867,U+DE3E
 UTF-8   では F0 A9 B8 BD の 4 バイト
 UTF-7  では 2B 32 47 66 65 50 51 2D の 7 バイト
であらわされることになります。



> そもそも「サロゲート文字」というように「文字」を末尾に付ける表現自体おかしい。
単独で使われる物ではないので、こうした単位を「文字」と呼んで良いのかは確かに微妙ですが、
U+D800~U+DFFF の範囲の文字をサロゲート文字と呼ぶことはあるので、さほどおかしくはないかも。

たとえば .NET には Char.IsSurrogate というメソッドがあるのですが、この戻り値は
 「引数が 0x00D800 以上 0x00DFFF 以下の文字なら true を返し、それ以外は false を返す」
という実装です。Char 構造体を「文字」として捉えるなら、これはサロゲート文字の判定と言えそうです。

前回と説明が被りますが、
U+D800〜U+DBFF までの 1024 個が上位サロゲート(high surrogate)文字で
U+DC00~U+DFFF までの 1024 個が下位サロゲート(low surrogate)文字です。
上位と下位の組であらわされるものをサロゲートペア(代用対; surrogate pair)と呼びます。


U+D800~U+DFFF の範囲は、Unicode (および ISO/IEC 10646) では文字が割り当てられておらず、
サロゲートペア(代用対)にしか使われません。その意味では確かに「文字」と呼ぶのは
微妙なところもあるのですが、.NET の世界だと、この 16bit 単位を System.Char 構造体として
いわゆる文字(Character)と扱ってきたという歴史的な背景もあります(内部表現は UTF-16)ので、
文意によってはこれも文字と言えます。

なお最近は、「U+D7FF 以下の 1 Char」あるいは「サロゲートペアな 2 Char」を一つの単位として、
ルーン(System.Text.Rune 構造体)という用語で扱われることが稀にあります。
https://docs.microsoft.com/en-us/dotnet/api/system.text.rune?view=net-6.0#convert-a-rune-to-utf-8-or-utf-16


> (例えばU+29E3D(ホッケ)は「サロゲート文字」である。)
こちらは正しい表現とは言い難いですね。
『U+29E3D は、(UTF-16 において)サロゲートペアで表現される文字である』、ならば良いかな?

U+29E3D「𩸽」を、文字コードが UTF-16 前提の処理系で扱う場合においては、
結果的にそれがサロゲートペアの U+D867,U+DE3E という組であらわされます。

この時の U+D867 や U+DE3E はサロゲートですので、UTF-16 という条件下に限れば
文意によっては完全に間違いとも言いきれない面はあるのですが…それでもやはり、
U+29E3D をサロゲート文字と呼んでしまうのは、いささか乱暴かなと思います。


> UTF-8では漢字等は3バイトで表現するので
漢字表現が 3 バイトよりもさらに増えることもあります。たとえば異体字。

墓地管理などのため、くさかんむり(艸部)の「艹」「艹」「艹」の違いを表現する必要がある場合に、
Variation Selector を併用した異体字漢字表現が使われることがあります。あとは結合文字とか。
https://ja.wikipedia.org/wiki/%E7%95%B0%E4%BD%93%E5%AD%97%E3%82%BB%E3%83%AC%E3%82%AF%E3%82%BF
https://fontnavi.jp/zakkuri/307-IVS.aspx


先の U+29E3D 「𩸽」でいえば、文字情報基盤整備事業の Moji_Joho コレクション対応フォントだと
 U+29E3D,U+E0102「𩸽󠄂」 MJ055217 {艹}{𠤎}
 U+29E3D,U+E0103「𩸽󠄃」 MJ055216 {艹}{𠤎}
 U+29E3D,U+E0104「𩸽󠄄」 MJ055218 {艹}{匕}
というシーケンスで区別されます。実際の字形は下記 URL の下の方をご覧ください。
https://747.github.io/vsselector/#!/ja/29e3d

上記のそれぞれ、たとえば U+29E3D,U+E0102 を見ると、それ自体はサロゲート文字ではないものの、
それを UTF-16 で符号化すると U+D867,U+DE3D,U+DB40,U+DD02 の 8 バイトになり、
符号化された結果は、 2 組のサロゲートペア(4 つのサロゲート文字)となります。
投稿者 (削除されました)  () 投稿日時 2021/9/6 13:56:49
(削除されました)
投稿者 (削除されました)  () 投稿日時 2021/9/6 09:24:28
(削除されました)
投稿者 まこ  (社会人) 投稿日時 2021/9/6 07:27:35
魔界の仮面弁士様、ありがとうございます。

すみません。Webで見たのは、頭に「&」が付いていました。
よくWeb上でデコードに失敗した場合、表示できない文字がそのように表示されています。
#xxxxx;のxが5つは、xの後に4桁の16進数のつもりで書きましたが、分かりにくかったですね。
申し訳ありません。HTMLで文字をスカラー値で表す場合に用いて「文字参照」と呼ぶのですね。
こちらの件は了解しました。

サロゲートの件は、完全に私が勘違いしているみたいでした。
ご教示、頂いた内容を自分なりに解釈したのが↓です。

この文字は「サロゲート文字」である。という考え方をしていたのですが、
(例えばU+29E3D(ホッケ)は「サロゲート文字」である。)
これは、「UTF-16なら当てはまるが、UTF-8には当てはまらない」ので、
そもそも「サロゲート文字」というように「文字」を末尾に付ける表現自体おかしい。
「UTF-16においては、4バイトでないと表現できない文字」を「サロゲートペア」と呼ぶ。
と理解しましたが、合ってるでしょうか?
それとUTF-8では漢字等は3バイトで表現するので、そもそも「サロゲート自体存在しない」
との認識で合ってるでしょうか?

お忙しい時に恐縮です。お時間の空いた時でいいので、コメント頂ければ幸いです。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2021/9/6 05:03:06
最近忙しくてあまり巡回できていなかったので、久しぶりに回答。


> 「A」だったら「U+0041」のように表す。と覚えていたのですが、
そうですね。 Unicode スカラー値は U+10FFFF のように
接頭辞「U+」を付けた4〜6桁で表記されます。

この場合の Unicode は、「文字コード」ではなく「文字集合」の意味になります。
http://office-qa.com/win/win243.htm

たとえば UCS-4 の U+010000 の文字 “𐀀” (Linear B Syllable B008 A) は、
 UTF-8 ⇒ F0 90 80 80
 UTF-16BE ⇒ D8 00 DC 00
 UTF-16LE ⇒ 00 D8 00 DC
ですね。いずれも同じ文字ですが、符号化した時のバイナリ表現が異なります。


> Webなんかでは頭に「#」、末尾に「;」を付けて「#x0041;」のような表記があり、
具体的には、Web の『どこ』で使われていましたか?

たとえば HTML の場合、
    <p>𠮷野家</p>
のことを
    <p>&#x20BB7;野家';</p>
あるいは
    <p>&#134071;野家';</p>
と書けますし、C# であれば
    string A = "𠮷野家";
のことを
    string \u0041 = "\U00020BB7\x91CE\U5bb6";
あるいは
    string \u0041 = "\xd842\uDFB7\u91ce\U00005bb6";
などと書くことがあります。



> (2)又、前者(U+xxxx)は「コードポイント」と言うと思っているのですが、
言いますね。


> 後者(#xxxxx;)は何と呼べば良いのでしょうか?
x が 5 つですか? それとも、x の後に 4桁の 16進数ですか?
『どこ』で使われている表現なのか分からないと答えにくいです。

似ているのは HTML の文字参照ですが、この場合は頭に & が付くはずなのですよね。
https://ja.wikipedia.org/wiki/%E6%96%87%E5%AD%97%E5%8F%82%E7%85%A7

C# のエスケープ表現だと、「\u」 +4桁16進数 / 「\U」+8桁16進数 / 「\x」+1~4桁16進数でセミコロンは付きません。


> (3)コードポイントを一目見て、スカラー値が2バイト(&HFFFF)を超えているものは
> サロゲート文字と判断していいでしょうか?
エンコーディング次第なので、「文字コードによる」という答えになります。

UCS-4 の U+110000 以降の文字は、UTF-32 や UTF-16 や UTF-8 の文字コードでは表現できませんし、
U+10000 から U+10FFFF の範囲であっても、UTF-32 や UTF-8 ではサロゲートペアを使用しません。

UTF-16 では、UCS-4 にあって UCS-2 にない文字のうち、U+10000 から U+10FFFF の範囲をサロゲートペアとして表し、
ハイサロゲート(U+D800〜U+DBFF)とローサロゲート(U+DC00〜U+DFFF)の組み合わせで表現します。
投稿者 まこ  (社会人) 投稿日時 2021/9/5 21:15:52
プログラムとあまり関係ないですが、文字コードについて教えてください。

(1)文字をUnicodeスカラー値で表す場合、16進数表示で頭に「U+」を付けて
「A」だったら「U+0041」のように表す。と覚えていたのですが、
Webなんかでは頭に「#」、末尾に「;」を付けて「#x0041;」のような表記があり、
同じ文字を表しているのは判りますが、どのような使い分けがされるのでしょうか?

(2)又、前者(U+xxxx)は「コードポイント」と言うと思っているのですが、
後者(#xxxxx;)は何と呼べば良いのでしょうか?

(3)コードポイントを一目見て、スカラー値が2バイト(&HFFFF)を超えているものは
サロゲート文字と判断していいでしょうか?