概要
Luhnアルゴリズム(ルーンアルゴリズム)のチェックディジットの部分を算出する。
※確認したのは15桁の数値に対してのみ。
15桁の数字が、
846087729128569
の場合、7
がチェックディジットになる。
545762389823411
の場合、3
がチェックディジットになる。
実装
パワープレイしてるところあるけど気にしない方向で。。
色んな言語に移植しやすいはず、逆にね、、
php
/*
* 15桁の数値に対して、チェックディジットとして付与するべき数字を算出する。
* ※15桁じゃなくても多分大丈夫だけど、15桁以外は試してない
*/
function gen_checkdigit($num)
{
// ルーン・アルゴリズムの参考サイト
// https://www.gizmodo.jp/2013/07/post_12829.html
// https://qiita.com/yossyyossy/items/41369a37ba05dccf53a9
// チェックディジットを計算するために15桁を16桁に上げる
// ※1桁目が0になるようにする(1桁目をxにする)ために10を掛ける
// ※感覚としては、15桁の数字が 846087729128569 の場合、 846087729128569X という状態にする。
$num = $num * 10;
// 数値を文字配列へ変換する。
// 数値が 8460877291285690 の場合、
// 先頭(8)が$num_array[0]で、最後(0)が$num_array[15]
$num_array = str_split($num);
$kisu = 0;
// 奇数桁の計算。奇数桁の和を求める。
// この時点では1桁目(チェックディジット)は必ず0で、処理の最後にチェックディジットとして正しい数値を出す。
for ($idx = 1; $idx < sizeof($num_array); $idx += 2) {
$kisu += $num_array[$idx];
}
$gusu = 0;
// 偶数桁の計算。
// 偶数桁は2倍にする。ただし、2倍して2桁になる数字は1桁目と2桁目の和を使う。
for ($idx = 0; $idx < sizeof($num_array); $idx += 2) {
// 5*2 は 10 なので 1(1+0) を足す
// 6*2 は 12 なので 3(1+2) を足す
// 7*2 は 14 なので 5(1+4) を足す
// 8*2 は 16 なので 7(1+6) を足す
// 9*2 は 18 なので 9(1+8) を足す
// 2倍にして2桁にならない数は2倍した数値を足す
if ($num_array[$idx] == 5) {
$gusu += 1;
} else if ($num_array[$idx] == 6) {
$gusu += 3;
} else if ($num_array[$idx] == 7) {
$gusu += 5;
} else if ($num_array[$idx] == 8) {
$gusu += 7;
} else if ($num_array[$idx] == 9) {
$gusu += 9;
} else {
$gusu += $num_array[$idx] * 2;
}
}
// 上でやっている (奇数桁の和+偶数桁の和) % 10 が 0 となる場合、正しい番号となる。
// ※この時点では1桁目が 0 で固定なので、ほぼ正しくない番号
// (奇数桁の和+偶数桁の和)+ X(1桁目)) % 10 が 0 となる X を求めると、
// X がチェックディジットとして、1桁目に付与する数値となる。
$_ = $kisu + $gusu;
$digit = 0;
while (true) {
// 10で割り切れた時、breakする
if (($_ + $digit) % 10 == 0) {
break;
} else {
// 10で割り切れるまで、カウントアップし続ける
$digit++;
}
}
return $digit;
}