手軽屋
ツール一覧

NFKC正規化の基礎

Unicode UAX #15で定められた4種類の正規化形式(NFC・NFD・NFKC・NFKD)の違いを、具体的な変換例を通して解説します。全角・半角変換の裏側で何が起きているかを理解すると、文字化けや処理失敗の予防につながります。

1. なぜ正規化が必要か

Unicodeでは同じ「見た目」の文字が複数のコードポイントで表現できます。例えばドイツ語のÄは「Ä(U+00C4)」という1文字でも、「A(U+0041)+̈(U+0308 結合分音記号)」の2文字でも書けます。見た目は同じですが、バイナリ表現が違うため文字列比較が失敗します。Unicode UAX #15はこれを統一的な形に揃える4つの正規化形式を定めています。

2. NFCとNFD(正準等価)

NFC(Normalization Form Canonical Composition)は分解された文字を1つにまとめる形式。「A+̈」→「Ä」のように合成します。NFD(Decomposition)は逆で、「Ä」→「A+̈」と分解します。どちらの形式で揃えても文字列比較は安定しますが、Webやファイル名でよく使われるのはNFCです。両者は「正準等価(canonical equivalence)」と呼ばれ、見た目だけでなく意味も完全に同じ文字同士の変換です。

3. NFKCとNFKD(互換性等価)

NFKC・NFKDはより踏み込んだ正規化で、「見た目は似ているが書字方向や使われ方が異なる」文字も統一します。全角A(U+FF21)と半角A(U+0041)は文字としては別物ですが、NFKCでは半角Aに統一されます。半角カナア(U+FF71)と全角アも、NFKCで全角アに統一されます。これを「互換性等価(compatibility equivalence)」と呼びます。本ツールの「全角→半角」「半角カナ→全角カナ」変換はこのNFKCの考え方に基づいています。

4. JavaScript String.normalize()

現代のブラウザはECMAScript標準のString.prototype.normalize()メソッドで正規化を実行できます。"ABC123".normalize("NFKC")とすれば、瞬時に"ABC123"が返ります。本ツールも内部でこのAPIを呼び出してUnicode準拠の変換を保証しています。Node.js・Deno・最新のブラウザすべてで動作するため、自分でJavaScriptで処理を組む際もこの方法が標準です。

5. 半角カナの濁点問題

半角カナの「ガ」は実は「カ(U+FF76)+゙(U+FF9E)」の2文字構成です。NFKCを通すと、カは「カ」、゙は「゛」に変換されますが、続けて合成処理が入り、最終的に「ガ(U+30AC)」の1文字になります。本ツールはこの仕様に従い、半角ガを正しく全角ガに変換します。「半角+濁点」のままだと2文字扱いになり、文字数カウントや並べ替えで予期せぬ挙動を起こすため、NFKC正規化が必須です。

6. NFKCで失われる情報

NFKCは便利ですが「情報を捨てる」変換でもあります。全角Aと半角Aを区別したいケース(プログラミング言語の識別子vs文字列リテラルなど)ではNFKCを安易に使うべきではありません。住所録・名簿の整形では半角に揃えることが目的なので積極的に使いますが、ソースコード処理ではNFCを使う方が安全です。全角・半角変換ツールで「どのモードで変換すべきか」を選ぶ際の判断材料にしてください。

全角・半角変換ツールを開く