首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >生成Luhn校验和

生成Luhn校验和
EN

Stack Overflow用户
提问于 2009-09-13 22:04:06
回答 7查看 16.9K关注 0票数 17

有许多用于验证Luhn校验和的实现,但用于生成它们的实现很少。然而,在我的测试中,我遇到了这一个,它显示出它是有缺陷的,并且我不理解delta变量背后的逻辑。

我已经做了这个函数,应该会生成Luhn校验和,但是由于某些原因,我还没有理解生成的校验和在一半的时间内是无效的。

代码语言:javascript
复制
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);
}

下面是一些例子:

代码语言:javascript
复制
Luhn(3); // 37, invalid
Luhn(37); // 372, valid
Luhn(372); // 3728, invalid
Luhn(3728); // 37283, valid
Luhn(37283); // 372837, invalid
Luhn(372837); // 3728375, valid

我正在验证生成的校验和相对于此页,我在这里做错了什么?

供将来参考,以下是工作函数.

代码语言:javascript
复制
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变量,因为我们不需要它来实现这个目的,并验证:

代码语言:javascript
复制
function Luhn_Verify($number, $iterations = 1)
{
    $result = substr($number, 0, - $iterations);

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

    return false;
}
EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2009-09-13 22:12:02

编辑:对不起,我现在意识到你已经得到了我的全部答案,你只是错误地决定了哪个因素用于哪个数字。

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

你的因子被颠倒了,你将错误的数字乘以2,这取决于数字的长度。

看一看维基百科关于Luhn算法的文章

您的校验和一半时间无效的原因是,您的支票,一半的时间,您的数字有一个奇数,然后你翻倍错误的数字。

对于37283,当你从右边数的时候,你会得到这样的数字序列:

代码语言:javascript
复制
  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。

如果以0结尾的数字以20结尾,则该数字是有效的。

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

  1. 点击一个额外的零,所以你的号码从氧到xyxyxyxy0
  2. 计算新数的luhn校验和和
  3. 取之和,模数10,得到一个从0到10的个位数。
  4. 如果数字是0,那么恭喜,您的校验和数字是零。
  5. 否则,计算10位数,以得到最后一个数字所需的值,而不是那个零。

例子:号码是12345

  1. 点上0: 123450
  2. 计算123450的luhn校验和,这将导致 0 5 4 3 2 1 1 1 2 1 1 2<-因子0 10 4 6 2 2<-乘积0 1 0 4 6 2 2<-将这些加到: 0+1+0+4+6+2+2=15
  3. 取之和(15),模数10,等于5
  4. 数字(5),不是零。
  5. 计算10-5,给你5,最后一个数字应该是5.

结果是123455。

票数 10
EN

Stack Overflow用户

发布于 2010-12-04 09:46:02

您的php是错误的,它会导致无限循环。这是我正在使用的工作版本,从您的代码中修改

函数Luhn($number) { $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 $value 10;if ( != 0) {en21# 10;=abs();}=内嵌(‘’,());=#en28。strval($stack);返回$number; }

创建一个php并在本地主机Luhn(xxxxxxxx)中运行以确认。

票数 3
EN

Stack Overflow用户

发布于 2013-02-06 13:00:05

现在有一个基于最初问题/答案的github回购。看见

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

也可以在包装商那里买到

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1418964

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档