チェックディジットについて考える
はじめに
何かしらのコード(例えばJANコードなど)では末尾に1桁のチェックディジットを付加して誤り検出を行うことがしばしば見られる。チェックディジットの目的としては、手入力などによる入力ミスによる誤り検出である。最も起きる確率の大きい誤りは1文字の誤りであるため、一般に1文字の誤り検出は必要だろう。チェックディジットな存在しない場合、他の入力ミスのパターンとしては、連番で付番されるようなコードであれば次の入力値の入力してしまう(コードが199
であれば次のコードである200
を入力するなど)ことや、入力値の入れ替え、入力値を連続して入力してしまい特定の桁の入力をスキップする(コードが1234
のところを1224
と入力してしまうなど)、キーボードの配列による入力ミスなどが挙げられる。
あらゆる誤り検出を行おうとすると十分な冗長性が必要になるが、そこまで高性能なものを求めてはいないのか、よく見られるチェックディジットは1桁のものである。今回はそのような1桁のチェックディジットについて、多分こんなものだろうという程度の理解のために色々と考えてみる。
チェックディジットの理論
進数列を与える。これをにチェックディジットを加えて表現される列で誤り検出を行うことを考える。なお、この列を10進数で表現したときは以下のようになる。
このモデルを基に、今回はメインとして剰余に基づくチェックディジットについて考えてみる。この節の最後には剰余を利用しない別のアプローチによるチェックディジットの理論について簡単に展開をしてみる。
1桁の誤り検出
まずは、1桁の誤り検出について考えてみる。1桁の誤りが検出できるとは、誤りが生じた桁をで0ではない雑音として、各桁の組から判定用の集合への写像で
が任意のおよび、を満たすについて成り立つというものである。
これの構成の1つはパリティ符号の考え方を拡張すれば容易に構築することができる。パリティ符号では、ビットの各桁の和が偶数であるときに0をパリティビットとして付与するというものであるが、これをの場合と考え、一般のについて構成しなおせば、
により与えられるを満たすをチェックディジットとして採用するというものである(は代表元をもつ上でのによる剰余による同値類)。なお、を満たすものとする。の場合を考えればパリティ符号と同値になることがわかるだろう。
では、実際に1桁の誤り検出が可能であることを示そう。を単純に各桁の和を取り、による剰余を取ることを考えると、の構成より以下を満たす。
は明らかに準同型のため、
となり、仮定よりかつ、すなわちかつを満たすため、常にを満たす。はを満たせば十分であるが、のときはチェックディジットだけ進数となる。
1桁の誤り検出の一般化
1桁のチェックディジットにより1桁の誤りを検出できることを示したが、これではこれ以外の誤りの検出ができないため、多少の自由が欲しい。そこで、を準同型と仮定して拡張をしてみる。まず、が準同型のため、とすれば
と記述できる。ここから、自然にとして
と与えたとすると、上記の議論と同様にチェックディジットが得られる。ただし、
を考えると、である必要があるため、任意のについてが0またはの倍数ではない、すなわちは0でないかつとが互いに素であることが必要十分である。
また、議論においてはは準同型としたが、例えばコードの整数表現で考えれば、事前にについて可逆な写像を用いてコードを変換(例えばコードの各桁を並べ替えるなど)をして、を用いてもいいだろう。
2桁の誤りの検出
誤りが生じた桁をそれぞれ、それぞれの桁に対応する0でない雑音を考えると、1桁の誤り検出の場合と同様にして
が得られるが、一般ににすることはできない。しかしながら、ある一定の条件を設けることで検出可能な場合もある。
同じ誤りの検出
この誤りは、例えばと連続した同じ2桁をのように同じ2桁で誤った場合などのものである。この検出においては、となるため、がと互いに素となるようにを選べばよいことがわかる。
しかしながら、この制約は意外にも厳しい。例えば、1桁の誤り検出が可能かつ10進数値を扱う場合、として考えると1桁の誤り検出が可能な条件下でははが有効である。これらはすべて奇数であるため、は偶数となり、常にと互いに素ではない。つまり、どのようにを選択してもに対してのときに誤りを検知することができない(つまり、10%の確率で検出不可)。これの大きな原因としては10は2を素因数にもつことにある。
桁の入れ替わりの検出
まずは桁の入れ替わりを定式化する。入れ替わる桁をそれぞれとしたとき、の桁目と桁目を入れ替えたものをとする。このとき、は以下のように表現される。
これを基に、1桁の誤りの検出の可能なを適用することを考えると
となり、桁の入れ替わりの仮定よりとしてもよいため、かつがと互いに素となるようにを選択すれば、任意の位置の桁の入れ替わりの検出が可能である。しかし、を満たす必要があるため、任意の桁の入れ替えの検出は現実的には利用されない(に素数を選択して可能な限り検出できるようにするというのはある)。
しかしながら、この制約は上記でも述べたように意外にも厳しい。1桁の誤り検出が可能かつ10進数値を扱う場合、として考えると1桁の誤り検出が可能な条件下ではは偶数となり、常にと互いに素ではない。つまり、どのようにを選択してもに対する桁の入れ替わりにおいて検出不可なの組み合わせ(を満たす組み合わせ)が存在することとなる(つまり、約10%の確率で検出不可)。
剰余を利用しない検出手法(おまけ)
これまででは、剰余に基づくチェックディジットの与え方を示したが、ほかの与え方も存在する。基本となるのはパリティ符号ではあるが、ビットの各桁の和を考えるのではなく、ビットの状態を保持しておいて逐次的に検査対象のビットを走査して、1のビットが出現したら保持しているビットを反転するという操作を繰り返した結果をパリティビットとして付与するというものがある。つまるところ、ビット列に対してであれば全ての検査対象のビットについてxorすればいい。
これを漸化式により記述すると以下のようになり、のためのようにチェックディジットも得られる。
これを任意の進数列に対して適用するときは、についてのな対応表を定義することでチェックディジットを計算できる。最初の1桁の誤り検出の時に示したチェックディジットの計算式
に対応するは以下のような巡回置換により与えられる。
この巡回置換に着目して、整数だけでなく、もう少し代数的に扱ってみる。まず、を2項演算とした単準同型写像を与え、の元をそれぞれとする。このとき、は明らかに群である。チェックディジットの計算式は、、上の単位元をとしたとき以下を満たすで与えられる。
これをについて解くと
となるため、上で考えたとしてもの存在と一意性は保証される。
上で1桁の誤りの検出を考えるとにおける演算は単一の巡回置換の作用のため、1桁の誤りは巡回置換の長さの範囲、すなわち任意のの元で誤りの検出が可能であることが直ちにわかる。逆に、における演算を仮定せず、が群であることのみを仮定して考えてみる。として、をへ誤ったとする。、のようにおくと、
のような2つの関係式(2つ目は単なるチェックディジットの定義式)が与えられる。このとき、常にとなれば常に1桁の誤りの検出が可能といえる。これらの式を整理すると、以下の2つの関係式が得られ、および、は共役であることがわかる。
以上より、1桁の誤りが検出であるということを言い換えると、以下が成り立つことであるが、これは対偶を取ることで真であることが直ちに分かる。
つまり、の各桁に対して単射を与え、が群を成すならば上の演算により生成されたチェックディジットでは1桁の誤りの検出が可能といえる。
最後に隣接する2桁の入れ替えを検出する群について示そう。桁の入れ替えが桁目と桁目で発生したと考えると、上記と同様の議論により、誤りの検出が可能であることは
を満たすことであるが、これを満たすにはの元でを満たす必要がある。つまり、群が中心を持たないならば、上の演算により生成されたチェックディジットでは隣接する2桁の入れ替えの検出が可能といえる。
具体例
ここからは社会で用いられているいくつかのチェックディジットを紹介してみる。
JANコード
JANコードのチェックディジットの計算方法は以下で紹介されている。
この検査で用いているチェックディジットの計算は、12桁の10進数数値から剰余に基づく方法で、
を用いて計算をしているものである。つまり、JANコードのチェックディジットの特性としては、1桁の誤りを検出可能であり、隣接する桁の同じ誤りと桁の入れ替わりそれぞれを90%程度で検出可能というものである。オーソドックスの見本ともいえる手法だろう。
法人番号
法人番号のチェックディジットの計算方法は以下で紹介されている。
この検査で用いているチェックディジットの計算は、12桁の10進数数値から剰余に基づく方法で、
を用いて計算をしているものである。つまり、法人番号のチェックディジットの特性としては、1桁の誤りと隣接する桁の入れ替わりをそれぞれを90%程度で検出可能というものである。隣接する桁の同じ誤りについては特に設計はされていない。設計ミスしているのでは。
個人番号
個人番号(マイナンバー)のチェックディジットの計算方法は以下で紹介されている。
この検査で用いているチェックディジットの計算は、11桁の10進数数値から剰余に基づく方法で、
を用いて計算をしているものである。ただし、チェックディジットが10となった場合は0として扱う。つまり、個人番号のチェックディジットの特性としては、1桁の誤りと隣接する桁の同じ誤り、桁の入れ替わりそれぞれを90%程度で検出可能というものである。設計ミスしているのでは。
同様の手法は、桁数が異なるだけで以下のチェックディジットでも用いられている。
住民票コード
全国地方公共団体コード
運転免許証番号
おわりに
チェックディジットをなんとなく理解するために理論を展開してみたが、実運用ではかなり雑にチェックディジットが利用されているように感じた(法人番号など)。もっと世界に目を広げればそうではないかもしれないが、興味があるのは実運用ではなくアルゴリズムの方であるため、特に気にしないでおく。
今回雑に展開をしてみたチェックディジットの理論については、あくまでも基本的なものであり、実用を考えると1桁ではなく2桁以上のチェックディジットを利用することの検討であったり、様々な誤りパターンへの対応などと考えるべき事柄はたくさんある。しかしながら、今回の記事で基本的な考え方は展開できたと思うので、別にいいだろう。