This commit is contained in:
krahets
2026-03-30 08:17:41 +08:00
parent 68cafe99dd
commit 46bccf0065
484 changed files with 60193 additions and 20315 deletions
@@ -6,7 +6,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="アニメーション図解ワンクリック実行データ構造とアルゴリズムチュートリアル">
<meta name="description" content="アニメーション図解ワンクリック実行コードで学べるデータ構造とアルゴリズムの入門書">
<meta name="author" content="krahets">
@@ -117,7 +117,7 @@
<path
d="M480 32c0-12.9-7.8-24.6-19.8-29.6s-25.7-2.2-34.9 6.9L381.7 53c-48 48-113.1 75-181 75H192 160 64c-35.3 0-64 28.7-64 64v96c0 35.3 28.7 64 64 64l0 128c0 17.7 14.3 32 32 32h64c17.7 0 32-14.3 32-32V352l8.7 0c67.9 0 133 27 181 75l43.6 43.6c9.2 9.2 22.9 11.9 34.9 6.9s19.8-16.6 19.8-29.6V300.4c18.6-8.8 32-32.5 32-60.4s-13.4-51.6-32-60.4V32zm-64 76.7V240 371.3C357.2 317.8 280.5 288 200.7 288H192V192h8.7c79.8 0 156.5-29.8 215.3-83.3z" />
</svg>
<span>日本語版審閱者を募集しています!詳細<a href="https://github.com/krahets/hello-algo/blob/main/ja/CONTRIBUTING.md">CONTRIBUTING.md</a>参照してください。</span>
<span>日本語版のレビュアーを募集しています。詳しく<a href="/ja/chapter_appendix/contribution/">こちら</a>ご覧ください。</span>
</div>
</div>
@@ -341,7 +341,7 @@
<span class="md-ellipsis">
はじめに
@@ -358,7 +358,7 @@
<span class="md-nav__icon md-icon"></span>
はじめに
</label>
@@ -618,7 +618,7 @@
<span class="md-ellipsis">
1.1 &nbsp; アルゴリズムはどこにでもある
1.1 &nbsp; アルゴリズムは至るところにある
@@ -646,7 +646,7 @@
<span class="md-ellipsis">
1.2 &nbsp; アルゴリズムとは何か
1.2 &nbsp; アルゴリズムとは
@@ -783,7 +783,7 @@
<span class="md-ellipsis">
2.1 &nbsp; アルゴリズム効率評価
2.1 &nbsp; アルゴリズム効率評価
@@ -1062,7 +1062,7 @@
<span class="md-ellipsis">
3.3 &nbsp; 数値の符号化 *
3.3 &nbsp; 数値エンコーディング *
@@ -1099,7 +1099,7 @@
<span class="md-ellipsis">
3.4 &nbsp; 文字の符号化 *
3.4 &nbsp; 文字エンコーディング *
@@ -1117,7 +1117,7 @@
<span class="md-ellipsis">
3.4 &nbsp; 文字の符号化 *
3.4 &nbsp; 文字エンコーディング *
@@ -1147,7 +1147,7 @@
<a href="#341-ascii" class="md-nav__link">
<span class="md-ellipsis">
3.4.1 &nbsp; ASCII文字セット
3.4.1 &nbsp; ASCII 文字セット
</span>
</a>
@@ -1158,7 +1158,7 @@
<a href="#342-gbk" class="md-nav__link">
<span class="md-ellipsis">
3.4.2 &nbsp; GBK文字セット
3.4.2 &nbsp; GBK 文字セット
</span>
</a>
@@ -1169,7 +1169,7 @@
<a href="#343-unicode" class="md-nav__link">
<span class="md-ellipsis">
3.4.3 &nbsp; Unicode文字セット
3.4.3 &nbsp; Unicode 文字セット
</span>
</a>
@@ -1180,7 +1180,7 @@
<a href="#344-utf-8" class="md-nav__link">
<span class="md-ellipsis">
3.4.4 &nbsp; UTF-8エンコーディング
3.4.4 &nbsp; UTF-8 エンコーディング
</span>
</a>
@@ -1191,7 +1191,7 @@
<a href="#345" class="md-nav__link">
<span class="md-ellipsis">
3.4.5 &nbsp; プログラミング言語における文字エンコーディング
3.4.5 &nbsp; プログラミング言語文字エンコーディング
</span>
</a>
@@ -1696,7 +1696,7 @@
<span class="md-ellipsis">
第 6 章 &nbsp; ハッシュ
第 6 章 &nbsp; ハッシュテーブル
@@ -1718,7 +1718,7 @@
<span class="md-nav__icon md-icon"></span>
第 6 章 &nbsp; ハッシュ
第 6 章 &nbsp; ハッシュテーブル
</label>
@@ -1740,7 +1740,7 @@
<span class="md-ellipsis">
6.1 &nbsp; ハッシュ
6.1 &nbsp; ハッシュテーブル
@@ -2047,7 +2047,7 @@
<span class="md-ellipsis">
7.5 &nbsp; AVL木 *
7.5 &nbsp; AVL 木 *
@@ -2210,7 +2210,7 @@
<span class="md-ellipsis">
8.2 &nbsp; ヒープ構築操作
8.2 &nbsp; ヒープ構築
@@ -2596,7 +2596,7 @@
<span class="md-ellipsis">
10.2 &nbsp; 二分探索の挿入
10.2 &nbsp; 二分探索の挿入位置
@@ -2652,7 +2652,7 @@
<span class="md-ellipsis">
10.4 &nbsp; ハッシュ最適化戦略
10.4 &nbsp; ハッシュによる最適化戦略
@@ -2680,7 +2680,7 @@
<span class="md-ellipsis">
10.5 &nbsp; 探索アルゴリズムの再認識
10.5 &nbsp; 探索アルゴリズム再考
@@ -3218,7 +3218,7 @@
<span class="md-ellipsis">
12.1 &nbsp; 分割統治アルゴリズム
12.1 &nbsp; 分割統治
@@ -3274,7 +3274,7 @@
<span class="md-ellipsis">
12.3 &nbsp; 木の構築問題
12.3 &nbsp; 二分木の構築問題
@@ -3302,7 +3302,7 @@
<span class="md-ellipsis">
12.4 &nbsp; ハノイの塔問題
12.4 &nbsp; ハノイの塔問題
@@ -3495,7 +3495,7 @@
<span class="md-ellipsis">
13.3 &nbsp; 部分集合和問題
13.3 &nbsp; 部分和問題
@@ -3523,7 +3523,7 @@
<span class="md-ellipsis">
13.4 &nbsp; Nクイーン問題
13.4 &nbsp; n クイーン問題
@@ -3664,7 +3664,7 @@
<span class="md-ellipsis">
14.1 &nbsp; 動的計画法の初歩
14.1 &nbsp; 動的計画法入門
@@ -3692,7 +3692,7 @@
<span class="md-ellipsis">
14.2 &nbsp; DP 問題特性
14.2 &nbsp; 動的計画法の問題特性
@@ -3720,7 +3720,7 @@
<span class="md-ellipsis">
14.3 &nbsp; DP の解法の考え方
14.3 &nbsp; 動的計画法の問題解決の考え方
@@ -3748,7 +3748,7 @@
<span class="md-ellipsis">
14.4 &nbsp; 0-1ナップサック問題
14.4 &nbsp; 0-1 ナップサック問題
@@ -3941,7 +3941,7 @@
<span class="md-ellipsis">
15.1 &nbsp; 貪欲アルゴリズム
15.1 &nbsp; 貪欲
@@ -4186,7 +4186,7 @@
<span class="md-ellipsis">
16.2 &nbsp; 一緒に作に参加する
16.2 &nbsp; 一緒に作に参加しましょう
@@ -4332,7 +4332,7 @@
<a href="#341-ascii" class="md-nav__link">
<span class="md-ellipsis">
3.4.1 &nbsp; ASCII文字セット
3.4.1 &nbsp; ASCII 文字セット
</span>
</a>
@@ -4343,7 +4343,7 @@
<a href="#342-gbk" class="md-nav__link">
<span class="md-ellipsis">
3.4.2 &nbsp; GBK文字セット
3.4.2 &nbsp; GBK 文字セット
</span>
</a>
@@ -4354,7 +4354,7 @@
<a href="#343-unicode" class="md-nav__link">
<span class="md-ellipsis">
3.4.3 &nbsp; Unicode文字セット
3.4.3 &nbsp; Unicode 文字セット
</span>
</a>
@@ -4365,7 +4365,7 @@
<a href="#344-utf-8" class="md-nav__link">
<span class="md-ellipsis">
3.4.4 &nbsp; UTF-8エンコーディング
3.4.4 &nbsp; UTF-8 エンコーディング
</span>
</a>
@@ -4376,7 +4376,7 @@
<a href="#345" class="md-nav__link">
<span class="md-ellipsis">
3.4.5 &nbsp; プログラミング言語における文字エンコーディング
3.4.5 &nbsp; プログラミング言語文字エンコーディング
</span>
</a>
@@ -4421,69 +4421,69 @@
<!-- Page content -->
<h1 id="34">3.4 &nbsp; 文字エンコーディング *<a class="headerlink" href="#34" title="Permanent link">&para;</a></h1>
<p>コンピュータシステムでは、すべてのデータ二進形式で格納され、<code>char</code>も例外ではありません。文字を表現するために、各文字と二進数の一対一のマッピングを定義する「文字セット」を開発する必要があります。文字セットがあれば、コンピュータは表を参照して二進数を文字に変換できます。</p>
<h2 id="341-ascii">3.4.1 &nbsp; ASCII文字セット<a class="headerlink" href="#341-ascii" title="Permanent link">&para;</a></h2>
<p><u>ASCIIコード</u>は最も初期の文字セットの一つで、正式にはAmerican Standard Code for Information Interchangeとして知られています。7つの二進1バイトの下位7ビット)を使用して文字を表し、最大128種類の異なる文字を表現できます。以下の図に示すように、ASCIIには英の大文字と小文字、0〜9の数字、様々な句読点、特定の制御文字(改行やタブなど)が含まれています。</p>
<p><img alt="ASCIIコード" class="animation-figure" src="../character_encoding.assets/ascii_table.png" /></p>
<p align="center"> 図 3-6 &nbsp; ASCIIコード </p>
<p>コンピュータでは、すべてのデータ二進数の形で保存されており、文字 <code>char</code> も例外ではありません。文字を表すためには、「文字セット」を定義し、各文字と二進数の間の一対一の対応関係を定める必要があります。文字セットがあれば、コンピュータは対応表を参照して二進数から文字への変換を行えます。</p>
<h2 id="341-ascii">3.4.1 &nbsp; ASCII 文字セット<a class="headerlink" href="#341-ascii" title="Permanent link">&para;</a></h2>
<p><u>ASCII コード</u>は最も早く登場した文字セットで、その正式名称は American Standard Code for Information Interchange(米国標準情報交換コード)です。これは 7 ビットの二進1 バイトの下位 7 ビット)で 1 文字を表し、最大128 種類の異なる文字を表現できます。下図のように、ASCII コードには英の大文字と小文字、数字 0 ~ 9、いくつかの句読点、そしていくつかの制御文字(改行やタブなど)が含まれます。</p>
<p><img alt="ASCII コード" class="animation-figure" src="../character_encoding.assets/ascii_table.png" /></p>
<p align="center"> 図 3-6 &nbsp; ASCII コード </p>
<p>しかし、<strong>ASCIIは英語の文字のみを表現できま</strong>。コンピュータのグローバル化に伴い、より多くの言語を表現するために<u>EASCII</u>と呼ばれる文字セットが開発されました。ASCIIの7ビット構造から8ビット拡張し、256文字表現を可能にしました</p>
<p>世界的に、様々な地域固有のEASCII文字セットが導入されました。これらのセットの最初の128文字はASCIIと一致していますが、残りの128文字は異なる言語の要件に対応するために異なって定義されています。</p>
<h2 id="342-gbk">3.4.2 &nbsp; GBK文字セット<a class="headerlink" href="#342-gbk" title="Permanent link">&para;</a></h2>
<p>後に、**EASCIIでも多くの言語の文字要件を満たすことができない**ことが判明しました。例えば、中国語には約10万の漢字があり、そのうち数千が定期的に使用されています。1980年、中国標準化委員会は6763の中国語文字を含む<u>GB2312</u>文字セットを発表し、中国語のコンピュータ処理ニーズを本質的に満たしました。</p>
<p>しかし、GB2312は一部の稀少文字や繁体字を処理できませんでした<u>GBK</u>文字セットはGB2312を拡張し、21886の中国語文字を含んでいます。GBKエンコーディングスキームでは、ASCII文字は1バイトで表現され、中国語文字は2バイトを使用します。</p>
<h2 id="343-unicode">3.4.3 &nbsp; Unicode文字セット<a class="headerlink" href="#343-unicode" title="Permanent link">&para;</a></h2>
<p>コンピュータ技術急速発展と多数の文字セットおよびエンコーディング標準により、数多くの問題が発生しました。一方では、これらの文字セットは一般的に特定の言語の文字のみを定義し、多言語環境では適切に機能できませんでした。方では、同じ言語に対する複数の文字セット標準の存在により、異なるエンコーディング標準を使用するコンピュータ間で情報交換を行う際に文字化けが発生しました。</p>
<p>当時の研究者たちは考えました<strong>世界のすべての言語と記号を含む包括的な文字セットが開発されれば、言語横断環境文字化けに関連する問題を解決できるのではないでしょうか?</strong> このアイデアにインスパイアされて、広範囲な文字セットであるUnicodeが誕生しました。</p>
<p><u>Unicode</u>中国語で「统一码」(統一コード)と呼ばれ、理論的に100万文字以上を収容できます。世界中のすべての文字を単一のセットに組み込み、様々な言語の処理表示のための汎用文字セットを提供し、異なるエンコーディング標準による文字化けの問題を減らすことを目指しています。</p>
<p>1991年のリリース以来、Unicodeは新しい言語と文字を含むよう継続的に拡張されています。2022年9月現在、Unicodeには149,186文字が含まれており、様々な言語の文字、記号、さらには絵文字も含まれています。大なUnicode文字セットでは、一般的に使用される文字は2バイトを占有し、一部の稀少な文字は3バイトまたは4バイトを占有する場合があります。</p>
<p>Unicodeは各文字に数値(「コードポイント」と呼ばれる)を割り当てる汎用文字セットですが、<strong>れらの文字コードポイントコンピュータシステムにどのように格納されるべきかは指定していません</strong>。疑問が生じるかもしれません:システムはテキスト内の異なる長さのUnicodeコードポイントをどのように解釈するのでしょうか?例えば、2バイトのコードが与えられた場合、システムはそれが単一の2バイト文字を表すのか、2つの1バイト文字を表すのかをどのように判断するのでしょうか</p>
<p><strong>この問題に対する簡単な解決策は、すべての文字を等長エンコーディングとして格納することです</strong>。以下の図に示すように、「Hello」の各文字は1バイトを占有し、「算法」(アルゴリズムの各文字は2バイトを占有します。上位ビットをゼロで埋めることで、「Hello 算法」のすべての文字を2バイトとしてエンコードできます。この方法により、システムは2バイトごとに文字を解釈し、フレーズの内容を復元できます。</p>
<p><img alt="Unicodeエンコーディング例" class="animation-figure" src="../character_encoding.assets/unicode_hello_algo.png" /></p>
<p align="center"> 図 3-7 &nbsp; Unicodeエンコーディング例 </p>
<p>しかし、<strong>ASCII コードで表現できるのは英語だけで</strong>。コンピュータのグローバル化に伴い、より多くの言語を表せる <u>EASCII</u> 文字セットが生まれました。これは ASCII の 7 ビットを 8 ビット拡張したもので、256 種類の異なる文字表現できます</p>
<p>世界では、さまざまな地域に適した EASCII 文字セットが次々に登場しました。これらの文字セットでは、前半の 128 文字は ASCII コードで統一され、後半の 128 文字は言語の要件に合わせて個別に定義されています。</p>
<h2 id="342-gbk">3.4.2 &nbsp; GBK 文字セット<a class="headerlink" href="#342-gbk" title="Permanent link">&para;</a></h2>
<p>その後、人々は**EASCII コードでも多くの言語に必要な文字数を満たせない**ことに気づきました。たとえば漢字は 10 万字近くあり、日常的に使うものだけでも数千字あります。中国国家標準総局は 1980 年に <u>GB2312</u> 文字セットを公開し、6763 字の漢字を収録して、漢字のコンピュータ処理の基本的な需要を満たしました。</p>
<p>しかし、GB2312は一部の珍しい字や繁体字を扱えません<u>GBK</u> 文字セットは GB2312 を基に拡張されたもので、合計 21886 字の漢字を収録しています。GBKエンコーディング方式では、ASCII 文字は 1 バイト、漢字は 2 バイトで表されます。</p>
<h2 id="343-unicode">3.4.3 &nbsp; Unicode 文字セット<a class="headerlink" href="#343-unicode" title="Permanent link">&para;</a></h2>
<p>コンピュータ技術急速発展するにつれて、文字セットと符号化規格は百花繚乱の状態となり、それに伴って多くの問題も生じました。一方では、これらの文字セットは通常、特定の言語の文字しか定義しておらず、多言語環境では正常に動作できませんでした。もう一方では、同じ言語に複数の文字セット規格が存在し、2 台のコンピュータが異なる符号化規格を使っていると、情報伝達の際に文字化けが発生しました。</p>
<p>当時の研究者たちはこう考えました<strong>十分に完全な文字セットを打ち出して、世界中のあらゆる言語と記号をそこに収録すれば、言語環境文字化け問題を解決できるのではない</strong>この発想に後押しされて、大規模で包括的な文字セット Unicode が誕生しました。</p>
<p><u>Unicode</u>中国語名は「統一コード」であり、理論上は 100 万を超える文字を収容できます。Unicode は世界中の文字を 1 つの文字セットに統合することを目指し、さまざまな言語の文字を処理表示できる汎用文字セットを提供することで、符号化規格の違いによる文字化けを減らそうとしています。</p>
<p>1991 年の公開以来、Unicode は新しい言語と文字を継続的に拡充してきました。2022 年 9 月時点で、Unicode にはすでに 149186 文字が含まれており、各種言語の文字、記号、さらには絵文字まで収録されています。大な Unicode 文字セットでは、よく使われる文字は 2 バイトを占、一部の珍しい文字は 3 バイト、さらには 4 バイトを占めます。</p>
<p>Unicode は汎用文字セットであり、本質的には各文字に番号(「コードポイント」)を割り当てるものですが、<strong>れらのコードポイントコンピュータ内でどのように保存するかまでは規定していません</strong>ここで疑問が生じます。長さの異なる Unicode コードポイントが同じテキストに現れたとき、システムはどのように文字を解析するのでしょうか。たとえば長さ 2 バイトの符号が与えられたとき、それが 2 バイトの 1 文字なのか、1 バイトの 2 文字なのかをどう判定するのでしょうか</p>
<p>この問題に対して、**すべての文字を固定長の符号として保存する**という直接的な解決策があります。下図のように、「Hello」の各文字は 1 バイト、「アルゴリズムの各文字は 2 バイトを占ます。上位ビットを 0 で埋めることで、「Hello アルゴリズム」のすべての文字を 2 バイト長にエンコードできます。こうすれば、システムは 2 バイトごとに 1 文字を解析して、この語句の内容を復元できます。</p>
<p><img alt="Unicode エンコーディング例" class="animation-figure" src="../character_encoding.assets/unicode_hello_algo.png" /></p>
<p align="center"> 図 3-7 &nbsp; Unicode エンコーディング</p>
<p>しかしASCIIが示したように、英語のエンコーディングには1バイトのみが必要です。上記のアプローチを使用すると、英語テキストが占有する空間ASCIIエンコーディングと比較して2倍になり、メモリ空間の無駄になります。したがって、より効率的なUnicodeエンコーディング方が必要です。</p>
<h2 id="344-utf-8">3.4.4 &nbsp; UTF-8エンコーディング<a class="headerlink" href="#344-utf-8" title="Permanent link">&para;</a></h2>
<p>現在、UTF-8は国際的に最も広く使用されているUnicodeエンコーディング方になっています。**これは可変長エンコーディング**で、文字の複雑さに応じて1〜4バイトを使用して文字を表現します。ASCII文字は1バイトのみが必要で、ラテン文字とギリシャ文字は2バイト、一般的に使用される中国語文字は3バイト、その他の稀少な文字は4バイト必要です。</p>
<p>UTF-8のエンコーディング規則は複雑ではなく、2つのケースに分けることができます</p>
<p>しかし ASCII コードはすでに、英語の符号化には 1 バイトで十分であることを示しています。上記の方式を採用すると、英語テキストが占る空間ASCII エンコーディング時の 2 倍になり、メモリ空間の浪費が大きくなります。そのため、より効率的な Unicode エンコーディング方が必要です。</p>
<h2 id="344-utf-8">3.4.4 &nbsp; UTF-8 エンコーディング<a class="headerlink" href="#344-utf-8" title="Permanent link">&para;</a></h2>
<p>現在、UTF-8 は国際的に最も広く使れている Unicode エンコーディング方になっています。**これは可変長エンコーディング**であり、1 文字を 1 〜 4 バイトで表し、文字の複雑さに応じて長さが変わります。ASCII 文字は 1 バイト、ラテン文字とギリシャ文字は 2 バイト、一般的な漢字は 3 バイト、そのほかの一部の珍しい文字は 4 バイト必要です。</p>
<p>UTF-8 の符号化規則はそれほど複雑ではなく、次の 2 つのケースに分けられます</p>
<ul>
<li>1バイト文字の場合、最上位ビットを<span class="arithmatex">\(0\)</span>設定し、残りの7ビットをUnicodeコードポイントに設定します。注目すべきは、ASCII文字がUnicodeセットの最初の128コードポイントを占有することです。これは**UTF-8エンコーディングASCIIと後方互換性がある**ことを意味します。これは、UTF-8を使用して古いASCIIテキストを解析できることを意味します。</li>
<li>長さ<span class="arithmatex">\(n\)</span>バイトの文字(<span class="arithmatex">\(n &gt; 1\)</span>の場合、最初のバイトの上位<span class="arithmatex">\(n\)</span>ビットを<span class="arithmatex">\(1\)</span>に設定し、<span class="arithmatex">\((n + 1)^{\text{th}}\)</span>ビットを<span class="arithmatex">\(0\)</span>に設定します。2番目のバイトから、各バイトの上位2ビットを<span class="arithmatex">\(10\)</span>に設定します。残りのビットはUnicodeコードポイントを埋めるために使用されます。</li>
<li>長さ 1 バイト文字では、最上位ビットを <span class="arithmatex">\(0\)</span> にし、残りの 7 ビットを Unicode コードポイントに設定します。ここで注意すべきなのは、ASCII 文字が Unicode 文字セットの先頭 128 個のコードポイントを占めていることです。つまり、<strong>UTF-8 エンコーディングASCII コードと下位互換性があります</strong>。このため、UTF-8 を使て古い ASCII コードのテキストを解析できます。</li>
<li>長さ <span class="arithmatex">\(n\)</span> バイトの文字(ただし <span class="arithmatex">\(n &gt; 1\)</span>では、先頭バイトの上位 <span class="arithmatex">\(n\)</span> ビットをすべて <span class="arithmatex">\(1\)</span> にし、第 <span class="arithmatex">\(n + 1\)</span> ビットを <span class="arithmatex">\(0\)</span> に設定します。2 バイト目以降では、各バイトの上位 2 ビットをいずれも <span class="arithmatex">\(10\)</span> にし、残りのすべてのビットで文字の Unicode コードポイントを埋めます。</li>
</ul>
<p>以下の図は「Hello算法」のUTF-8エンコーディングを示しています。上位<span class="arithmatex">\(n\)</span>ビットが<span class="arithmatex">\(1\)</span>に設定されているため、システムは最上位ビットで<span class="arithmatex">\(1\)</span>に設定されたビット数を数えることで文字の長さ<span class="arithmatex">\(n\)</span>として決定できることが観察できます。</p>
<p>しかし、なぜ残りのバイトの上位2ビットを<span class="arithmatex">\(10\)</span>設定するのでしょうか?実際、この<span class="arithmatex">\(10\)</span>は一種のチェックサムとして機能します。システムが間違ったバイトからテキスト解析を開始した場合、バイト先頭の<span class="arithmatex">\(10\)</span>によりシステムは異常を迅速に検出できます。</p>
<p><span class="arithmatex">\(10\)</span>をチェックサムとして使用する理由は、UTF-8エンコーディング規則の下では、文字の最上位2ビットが<span class="arithmatex">\(10\)</span>になることは不可能だからです。これは矛盾により証明できます文字の上位2ビットが<span class="arithmatex">\(10\)</span>場合、文字の長さ<span class="arithmatex">\(1\)</span>であることを示し、これはASCIIに対応します。しかしASCII文字の最上位ビットは<span class="arithmatex">\(0\)</span>であるべきで、これは仮定と矛盾します。</p>
<p><img alt="UTF-8エンコーディング例" class="animation-figure" src="../character_encoding.assets/utf-8_hello_algo.png" /></p>
<p align="center"> 図 3-8 &nbsp; UTF-8エンコーディング例 </p>
<p>図は「Helloアルゴリズム」に対応する UTF-8 エンコーディングを示しています。観察すると、上位 <span class="arithmatex">\(n\)</span> ビットがすべて <span class="arithmatex">\(1\)</span> に設定されているため、システムは先頭から連続する <span class="arithmatex">\(1\)</span> の個数を読むことで、その文字の長さ<span class="arithmatex">\(n\)</span> であると解析できます。</p>
<p>では、なぜ残りのすべてのバイトの上位 2 ビットを <span class="arithmatex">\(10\)</span> にするのでしょうか。実は、この <span class="arithmatex">\(10\)</span> は検査用の印として機能します。システムがったバイト位置からテキスト解析し始めたとしても、バイト先頭の <span class="arithmatex">\(10\)</span> によって異常を素早く判定できます。</p>
<p>この <span class="arithmatex">\(10\)</span> を検査用の印とする理由は、UTF-8 の符号化規則では上位 2 ビットが <span class="arithmatex">\(10\)</span> になる文字は存在しないからです。この結論は背理法で証明できます。ある文字の上位 2 ビットが <span class="arithmatex">\(10\)</span> だと仮定すると、その文字の長さ<span class="arithmatex">\(1\)</span> であり、ASCII コードに対応することになります。しかし ASCII コードの最上位ビットは <span class="arithmatex">\(0\)</span> であるはずなので、仮定と矛盾します。</p>
<p><img alt="UTF-8 エンコーディング例" class="animation-figure" src="../character_encoding.assets/utf-8_hello_algo.png" /></p>
<p align="center"> 図 3-8 &nbsp; UTF-8 エンコーディング</p>
<p>UTF-8以外にも、他の一般的なエンコーディング方法には以下があります</p>
<p>UTF-8 以外にも、一般的なエンコーディング方式として次の 2 つがあります</p>
<ul>
<li><strong>UTF-16エンコーディング</strong>2または4バイトを使用して文字を表現します。すべてのASCII文字と一般的に使用される非英語文字は2バイトで表現され、少数の文字は4バイト必要す。2バイト文字の場合、UTF-16エンコーディングはUnicodeコードポイントと等しくなります。</li>
<li><strong>UTF-32エンコーディング</strong>すべての文字が4バイトを使用します。これは、UTF-32UTF-8UTF-16よりも多くの空間を占有することを意味し、特にASCII文字の割合が高いテキストで顕著です。</li>
<li><strong>UTF-16 エンコーディング</strong>1 文字を 2 バイトまたは 4 バイトで表します。すべての ASCII 文字と一般的非英語文字は 2 バイトで表し、一部の文字だけが 4 バイト必要とします。2 バイト文字については、UTF-16 エンコーディングは Unicode コードポイントと等しくなります。</li>
<li><strong>UTF-32 エンコーディング</strong>各文字を必ず 4 バイトで表します。つまり UTF-32UTF-8UTF-16 よりも多くの領域を消費し、とくに ASCII 文字の比率が高いテキストでその傾向が顕著です。</li>
</ul>
<p>ストレージ空間の観点から、UTF-8を使用して英語文字表現することは1バイトのみが必要なため非常に効率的です。UTF-16を使用して一部の非英語文字(中国語など)をエンコードすることは、2バイトのみが必要なためより効率的になる場合があります。一方、UTF-8では3バイト必要になる場合があります。</p>
<p>互換性の観点から、UTF-8は最も汎用性があり、多くのツールライブラリがUTF-8を優先的にサポートしています。</p>
<h2 id="345">3.4.5 &nbsp; プログラミング言語における文字エンコーディング<a class="headerlink" href="#345" title="Permanent link">&para;</a></h2>
<p>歴史的に、多くのプログラミング言語はプログラム実行中の文字列処理にUTF-16UTF-32などの固定長エンコーディングを利用していました。これにより文字列を配列として処理でき、いくつかの利点があります</p>
<p>記憶領域の使用量という観点では、UTF-8英語文字表現に非常に効率的で、必要なのは 1 バイトだけです。一方、UTF-16一部の非英語文字(たとえば中国語の文字)の符号化でより効率的になることがあり、必要なのは 2 バイトだけで、UTF-8 では 3 バイト必要になる場合があります。</p>
<p>互換性という観点では、UTF-8汎用性が最も高く、多くのツールライブラリが UTF-8 を優先的にサポートしています。</p>
<h2 id="345">3.4.5 &nbsp; プログラミング言語文字エンコーディング<a class="headerlink" href="#345" title="Permanent link">&para;</a></h2>
<p>従来の多くのプログラミング言語では、実行中の文字列に UTF-16UTF-32 のような固定長エンコーディングが使われています。固定長エンコーディングでは、文字列を配列のように扱えるため、次のような利点があります</p>
<ul>
<li><strong>ランダムアクセス</strong>UTF-16でエンコードされた文字列は簡単にランダムアクセスできます。可変長エンコーディングであるUTF-8の場合、<span class="arithmatex">\(i^{th}\)</span>文字の位置を特定するには文字列の開始から<span class="arithmatex">\(i^{th}\)</span>位置まで走査する必要があり、<span class="arithmatex">\(O(n)\)</span>時間がかかります。</li>
<li><strong>文字数カウント</strong>:ランダムアクセスと同様に、UTF-16でエンコードされた文字列の文字数をカウントすることは<span class="arithmatex">\(O(1)\)</span>操作です。しかし、UTF-8でエンコードされた文字列の文字数をカウントするには文字列全体を走査する必要があります。</li>
<li><strong>文字列操作</strong>分割、連結、挿入、削除などの多くの文字列操作は、UTF-16でエンコードされた文字列で簡単です。これらの操作は一般的に、UTF-8エンコーディングの有効性を確保するためにUTF-8でエンコードされた文字列で追加計算が必要です。</li>
<li><strong>ランダムアクセス</strong>UTF-16 で符号化された文字列はランダムアクセスが容易です。UTF-8 は可変長エンコーディングなので、第 <span class="arithmatex">\(i\)</span> 文字を見つけるには文字列の先頭から第 <span class="arithmatex">\(i\)</span> 文字まで走査する必要があり、<span class="arithmatex">\(O(n)\)</span>時間がかかります。</li>
<li><strong>文字数の計算</strong>:ランダムアクセスと同様に、UTF-16 で符号化された文字列の長さを計算するのも <span class="arithmatex">\(O(1)\)</span>操作です。しかし、UTF-8 で符号化された文字列の長さを計算するには文字列全体を走査する必要があります。</li>
<li><strong>文字列操作</strong>UTF-16 で符号化された文字列では、多くの文字列操作(分割、連結、挿入、削除など)をより簡単に行えます。UTF-8 で符号化された文字列では、これらの操作を行う際に、無効な UTF-8 エンコーディングを生じさせないための追加計算が通常必要になります。</li>
</ul>
<p>プログラミング言語における文字エンコーディングスキームの設計は、様々な要因を含む興味深いトピックです:</p>
<p>実際、プログラミング言語における文字エンコーディング方式の設計は、とても興味深い話題であり、多くの要因が関わっています。</p>
<ul>
<li>Java<code>String</code>型はUTF-16エンコーディングを使用し、各文字が2バイトを占有します。これは16ビットがすべての可能な文字を表現するのに十分であるという初期の信念に基づいており、後に間違いであることが証明されました。Unicode標準が16ビットを超えて拡張されると、Javaの文字は「サロゲートペア」として知られる16ビット値のペアで表される場合があります。</li>
<li>JavaScriptTypeScriptは、Javaと同様の理由でUTF-16エンコーディングを使用します。JavaScriptが1995年にNetscapeによって最初に導入されたとき、Unicodeはまだ初期段階にあり、16ビットエンコーディングはすべてのUnicode文字を表現するのに十分でした。</li>
<li>C#UTF-16エンコーディングを使用し、これは主にMicrosoftによって設計された.NETプラットフォーム、および多くのMicrosoft技術(Windowsオペレーティングシステムを含む)UTF-16エンコーディングを広範囲に使用しているためです。</li>
<li>Java<code>String</code> 型は UTF-16 エンコーディングを使用し、各文字は 2 バイトを占ます。これは Java 言語の設計当初、人々が 16 ビットあればあらゆる文字を表現するのに十分だと考えていたためです。しかし、これは誤った判断でした。その後 Unicode 規格は 16 ビットを超える範囲へ拡張されたため、現在の Java では 1 文字が 16 ビット値の組(「サロゲートペア」)で表されることがあります。</li>
<li>JavaScriptTypeScript の文字列が UTF-16 エンコーディングを使う理由も Java と似ています。1995 年に Netscape 社が初めて JavaScript 言語を公開した当時、Unicode はまだ発展初期にあり、16 ビットの符号化で十分すべての Unicode 文字を表せると考えられていました。</li>
<li>C#UTF-16 エンコーディングを使う主な理由は、.NET プラットフォームが Microsoft によって設計されMicrosoft の多くの技術(Windows オペレーティングシステムを含む)UTF-16 エンコーディングが広く使われているためです。</li>
</ul>
<p>文字数過小評価により、これらの言語は16ビットを超えるUnicode文字を表現するために「サロゲートペア」を使用する必要がありました。このアプローチには欠点があります:サロゲートペアを含む文字列は2バイトまたは4バイトを占有する文字を持つ場合があり、固定長エンコーディングの利点を失います。さらに、サロゲートペアの処理はプログラミング複雑さとデバッグの困難さを追加します。</p>
<p>れらの課題に対処するため、一部の言語は代替エンコーディング戦略を採用しています:</p>
<p>以上のプログラミング言語は文字数過小評価していたため、16 ビットを超える長さの Unicode 文字を表ために「サロゲートペア」を採用せざるを得ませんでした。これはやむを得ない妥協策です。一方では、サロゲートペアを含む文字列では、1 文字が 2 バイトまたは 4 バイトを占める可能性があり、固定長エンコーディングの利点が失われます。もう一方では、サロゲートペアの処理には追加のコードが必要となり、プログラミング複雑さとデバッグの難しさが増します。</p>
<p>うした理由から、一部のプログラミング言語では別のエンコーディング方式が採用されました。</p>
<ul>
<li>Python<code>str</code>型は、文字のストレージ長が文字列内の最大のUnicodeコードポイントに依存する柔軟な表現でUnicodeエンコーディングを使用します。すべての文字がASCIIの場合、各文字は1バイトを占有し、基本多言語面(BMP)内の文字は2バイト、BMPを超える文字は4バイトを占有します。</li>
<li>Go<code>string</code>型は内部的にUTF-8エンコーディングを使用します。Goは個別のUnicodeコードポイントを表現するための<code>rune</code>型も提供します。</li>
<li>Rust<code>str</code><code>String</code>型は内部的にUTF-8エンコーディングを使用します。Rustは個別のUnicodeコードポイント用の<code>char</code>型も提供します。</li>
<li>Python<code>str</code> は Unicode エンコーディングを使用し、柔軟な文字列表現を採用しています。保存される文字の長さは、その文字列中で最大の Unicode コードポイントに依存します。文字列がすべて ASCII 文字であれば各文字は 1 バイト、ASCII の範囲を超える文字があってもすべてが基本多言語面(BMP)内であれば各文字は 2 バイト、BMP を超える文字があれば各文字は 4 バイトを占ます。</li>
<li>Go 言語の <code>string</code> 型は内部UTF-8 エンコーディングを使用します。Go 言語には単一の Unicode コードポイントを表<code>rune</code> 型も用意されています。</li>
<li>Rust 言語の <code>str</code><code>String</code> 型は内部UTF-8 エンコーディングを使用します。Rust にも単一の Unicode コードポイントを表す <code>char</code> 型があります。</li>
</ul>
<p>上記の議論は、プログラミング言語での文字列の格納方法に関するものであり、**ファイルでの文字列の格納方法やネットワーク上での送信方法とは異なる**ことに注意することが重要です。ファイルストレージやネットワーク送では、文字列は通常、最適な互換性と空間効率のためにUTF-8形式エンコードされます。</p>
<p>注意すべきなのは、ここまでの議論はすべて、プログラミング言語での文字列の保存方法についてであり、**文字列をファイルに保存したりネットワークで転送したりする方法とは別の問題である**ということです。ファイル保存やネットワーク送では、通常、互換性と空間効率を最適化するために文字列を UTF-8 形式エンコードます。</p>
<!-- Source file information -->
@@ -4506,7 +4506,7 @@ aria-label="フッター"
<a
href="../number_encoding/"
class="md-footer__link md-footer__link--prev"
aria-label="前: 3.3 &amp;nbsp; 数値の符号化 *"
aria-label="前: 3.3 &amp;nbsp; 数値エンコーディング *"
rel="prev"
>
<div class="md-footer__button md-icon">
@@ -4518,7 +4518,7 @@ aria-label="フッター"
</span>
<div class="md-ellipsis">
3.3 &nbsp; 数値の符号化 *
3.3 &nbsp; 数値エンコーディング *
</div>
</div>
</a>