小编典典

生成Luhn校验和

algorithm

有许多实现可用于验证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;
}

阅读 599

收藏
2020-07-28

共1个答案

小编典典

编辑 :对不起,我现在意识到您已经几乎了解了我的全部答案,而您只是错误地确定了将哪个系数用于哪个数字。

我的整个答案现在可以用这句话概括:

您已将因子取反,您要根据数字的长度将错误的数字乘以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),则该数字有效。

现在,您的问题暗示您想知道如何生成校验和,很简单,请执行以下操作:

  1. 加上一个额外的零,因此您的数字从xyxyxyxy变为xyxyxyxy0
  2. 计算新数字的luhn校验和
  3. 取总和,模数为10,因此您得到的数字从0到10
  4. 如果数字为0,那么恭喜,您的校验和数字为零
  5. 否则,请计算10位数字以获得所需的最后一位数字,而不是零

示例:数字为12345

  1. 零击:123450
  2. 计算123450的luhn校验和,结果为
        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
  1. 取总和(15),模数10,得出5

  2. 数字(5),不为零

  3. 计算10-5,得出5,最后一位应为5。

因此结果是123455。

2020-07-28