有许多实现可用于验证Luhn校验和,但很少可用于生成它们。我遇到过这个问题,但是在我的测试中发现它有问题,而且我不了解delta变量背后的逻辑。
我做了这个功能,应该可以生成Luhn校验和,但是由于某种原因,我还不了解所生成的校验和在一半时间内是无效的。
function Luhn($number, $iterations = 1) { while ($iterations-- >= 1) { $stack = 0; $parity = strlen($number) % 2; $number = str_split($number, 1); foreach ($number as $key => $value) { if ($key % 2 == $parity) { $value *= 2; if ($value > 9) { $value -= 9; } } $stack += $value; } $stack = 10 - $stack % 10; if ($stack == 10) { $stack = 0; } $number[] = $stack; } return implode('', $number); }
一些例子:
Luhn(3); // 37, invalid Luhn(37); // 372, valid Luhn(372); // 3728, invalid Luhn(3728); // 37283, valid Luhn(37283); // 372837, invalid Luhn(372837); // 3728375, valid
我正在针对此页面验证生成的校验和,在这里我做错了什么?
供以后参考,这里是工作功能。
function Luhn($number, $iterations = 1) { while ($iterations-- >= 1) { $stack = 0; $number = str_split(strrev($number), 1); foreach ($number as $key => $value) { if ($key % 2 == 0) { $value = array_sum(str_split($value * 2, 1)); } $stack += $value; } $stack %= 10; if ($stack != 0) { $stack -= 10; } $number = implode('', array_reverse($number)) . abs($stack); } return $number; }
我删除了$ parity变量,因为我们不需要它,并进行以下验证:
function Luhn_Verify($number, $iterations = 1) { $result = substr($number, 0, - $iterations); if (Luhn($result, $iterations) == $number) { return $result; } return false; }
编辑 :对不起,我现在意识到您已经几乎了解了我的全部答案,而您只是错误地确定了将哪个系数用于哪个数字。
我的整个答案现在可以用这句话概括:
您已将因子取反,您要根据数字的长度将错误的数字乘以2。
看看有关Luhn算法的Wikipedia文章。
您的校验和有一半时间是无效的,原因是您的支票,一半的时间中您的数字有奇数个数字,然后您将错误的数字加倍。
对于37283,从右边数时,您会得到以下数字序列:
3 * 1 = 3 3 8 * 2 = 16 --> 1 + 6 = 7 2 * 1 = 2 2 7 * 2 = 14 --> 1 + 4 = 5 + 3 * 1 = 3 3 = 20
该算法要求您将原始数字中的各个数字相加,然后加上“从右边开始的两位数字”乘积的乘积中的各个数字。
因此,从右边看,您求和3 +(1 + 6)+ 2 +(1 + 4)+ 3,得出20。
如果最后得到的数字以零结尾(即20),则该数字有效。
现在,您的问题暗示您想知道如何生成校验和,很简单,请执行以下操作:
示例:数字为12345
0 5 4 3 2 1 1 2 1 2 1 2 <-- factor 0 10 4 6 2 2 <-- product 0 1 0 4 6 2 2 <-- sum these to: 0+1+0+4+6+2+2=15
取总和(15),模数10,得出5
数字(5),不为零
因此结果是123455。