生成卢恩校验(Generating Luhn Checksums)

2019-07-17 22:05发布

有很多实现的用于验证卢恩校验但对他们产生非常少。 我已经遇到这个然而,在我的测试中,它揭示了要马车,我不明白增量变量背后的逻辑。

我做了推测应该产生卢恩校验这个功能,但由于某种原因,我还没有认识到所产生的校验和的无效时间的一半。

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;
}

我放弃了$奇偶性变量,因为我们并不需要它用于此目的,并验证:

function Luhn_Verify($number, $iterations = 1)
{
    $result = substr($number, 0, - $iterations);

    if (Luhn($result, $iterations) == $number)
    {
        return $result;
    }

    return false;
}

Answer 1:

编辑 :对不起,我现在认识到,你就已经,您刚刚正确确定将使用为其数字哪种因素几乎我的整个的答案。

我的整个现在答案可以概括这个简单的句子:

你有逆转的因素,你被2取决于数量的长度乘以错误的数字。


看看在对卢恩算法维基百科的文章 。

原因你的校验和是无效的一半时间是与你的支票,有一半的时间你的电话号码有奇数个数字,然后你双倍的错误数字。

对于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 
  3. 就拿总和(15),模数10,它给你5

  4. 数字(5),是不为零
  5. 计算10-5,它给你5,最后一个数字应为5。

所以结果是123455。



Answer 2:

你的PHP是越野车,它会导致进入一个无限循环。 这是我使用的工作版本,从您的代码修改

功能卢恩($号){

 $stack = 0; $number = str_split(strrev($number)); foreach ($number as $key => $value) { if ($key % 2 == 0) { $value = array_sum(str_split($value * 2)); } $stack += $value; } $stack %= 10; if ($stack != 0) { $stack -= 10; $stack = abs($stack); } $number = implode('', array_reverse($number)); $number = $number . strval($stack); return $number; 

}

创建一个PHP和本地主机卢恩(XXXXXXXX)确认运行。



Answer 3:

我简直不敢相信有多少糟糕的实现也有在那里。

IDAutomation的拥有.NET程序集与MOD10()函数来创建,但它似乎没有工作。 在反射器的代码是太长了什么它应该是无论如何做。


页面的这个烂摊子这实际上是目前维基百科(!)链接至Javascript的有几个验证实现,当我打电话每一个甚至不返回相同的值。


在维基百科的卢恩页面链接到页面有一个JavaScript编码器,似乎工作:

// Javascript
String.prototype.luhnGet = function()
{
    var luhnArr = [[0,1,2,3,4,5,6,7,8,9],[0,2,4,6,8,1,3,5,7,9]], sum = 0;
    this.replace(/\D+/g,"").replace(/[\d]/g, function(c, p, o){
        sum += luhnArr[ (o.length-p)&1 ][ parseInt(c,10) ]
    });
    return this + ((10 - sum%10)%10);
};

alert("54511187504546384725".luhnGet());​

这是非常有用的EE4253页验证校验位,也显示了完整的计算和解释。


我需要C#代码,结束了使用此代码项目代码 :

// C#
public static int GetMod10Digit(string data)
        {
            int sum = 0;
            bool odd = true;
            for (int i = data.Length - 1; i >= 0; i--)
            {
                if (odd == true)
                {
                    int tSum = Convert.ToInt32(data[i].ToString()) * 2;
                    if (tSum >= 10)
                    {
                        string tData = tSum.ToString();
                        tSum = Convert.ToInt32(tData[0].ToString()) + Convert.ToInt32(tData[1].ToString());
                    }
                    sum += tSum;
                }
                else
                    sum += Convert.ToInt32(data[i].ToString());
                odd = !odd;
            }

            int result = (((sum / 10) + 1) * 10) - sum;
            return result % 10;
        }

这在C#中验证代码似乎工作,如果有点笨拙。 我只是用它来检查以上是正确的。



Answer 4:

现在有在原有基础上提问/回答一个GitHub库。 看到

https://github.com/xi-project/xi-algorithm

它也可在packagist



Answer 5:

这是一个功能,可以帮助你,因为它很短,它工作得很好。

function isLuhnValid($number)
{
    if (empty($number))
        return false;

    $_j = 0;
    $_base = str_split($number);
    $_sum = array_pop($_base);
    while (($_actual = array_pop($_base)) !== null) {
        if ($_j % 2 == 0) {
            $_actual *= 2;
            if ($_actual > 9)
                $_actual -= 9;
        }
        $_j++;
        $_sum += $_actual;
    }
    return $_sum % 10 === 0;
}


文章来源: Generating Luhn Checksums