生成卢恩校验 [英] Generating Luhn Checksums

查看:329
本文介绍了生成卢恩校验的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有很多实现的验证卢恩校验,但很少产生他们。不过,我已经遇到这个在我的测试中,它已经发现是车,我不明白背后的逻辑增量变量。

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

 函数卢恩($号码,$迭代= 1)
{
    而($ iterations--> = 1)
    {
    $堆栈= 0;
    $平价=的strlen($数)%2;
    $数= str_split($号,1);

    的foreach($号码作为$关键=> $值)
    {
    如果($关键%2 == $奇偶校验)
    {
    $值* = 2;

    如果($值GT; 9)
    {
    $值 -  = 9;
    }
    }

    $栈+ = $价值;
    }

    $堆栈= 10  -  $堆%10;

    如果($栈== 10)
    {
    $堆栈= 0;
    }

    $编号[] = $栈;
    }

    返回破灭('',$号);
}
 

一些例子:

 卢恩(3); // 37,无效
卢恩(37); // 372,有效
卢恩(372); // 3728,无效
卢恩(3728); // 37283,有效
卢恩(37283); // 372837,无效
卢恩(372837); // 3728375,有效期
 

我验证生成的校验反对这个页面,我究竟做错了什么?


对于未来的参考,在这里是工作的功能。

 函数卢恩($号码,$迭代= 1)
{
    而($ iterations--> = 1)
    {
    $堆栈= 0;
    $数= str_split(strrev($号),1);

    的foreach($号码作为$关键=> $值)
    {
    如果($关键%2 == 0)
    {
    $值= array_sum(str_split($值* 2,1));
    }

    $栈+ = $价值;
    }

    $堆栈(%)= 10;

    如果($堆叠!= 0)
    {
    $堆栈 -  = 10;
    }

    $数=破灭('',array_reverse($编号))。 ABS($栈);
    }

    返回$号;
}
 

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

 函数Luhn_Verify($号码,$迭代= 1)
{
    $结果= SUBSTR($数,0, -  $迭代);

    如果(卢恩($结果,$迭代)== $号)
    {
    返回$结果;
    }

    返回false;
}
 

解决方案

修改:对不起,我现在你几乎我所有的答案已经,你刚刚不正确地确定要使用哪个因素实现其中一位。

我的完整的答案,现在可以总结这个一句话:

您有因子逆转,你乘以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位数字,以获得您所需要的而不是零
  6. 最后一位数,

例如:号码为12345

  1. 钉在一个零:123450
  2. 计算LUHN校验123450,其导致

      0 5 4 3 2 1
    1 2 1 2 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。

There are lots of implementations for validating Luhn checksums but very few for generating them. I've come across this one however in my tests it has revealed to be buggy and I don't understand the logic behind the delta variable.

I've made this function that supposedly should generated Luhn checksums but for some reason that I haven't yet understood the generated checksums are invalid half of the time.

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

Some examples:

Luhn(3); // 37, invalid
Luhn(37); // 372, valid
Luhn(372); // 3728, invalid
Luhn(3728); // 37283, valid
Luhn(37283); // 372837, invalid
Luhn(372837); // 3728375, valid

I'm validating the generated checksums against this page, what am I doing wrong here?


For future reference, here is the working function.

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

I dropped the $parity variable since we don't need it for this purpose, and to verify:

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

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

    return false;
}

解决方案

Edit: Sorry, I realize now that you had almost my entire answer already, you had just incorrectly determined which factor to use for which digit.

My entire answer now can be summed up with this single sentence:

You have the factor reversed, you're multiplying the wrong digits by 2 depending on the length of the number.


Take a look at the Wikipedia article on the Luhn algorithm.

The reason your checksum is invalid half the time is that with your checks, half the time your number has an odd number of digits, and then you double the wrong digit.

For 37283, when counting from the right, you get this sequence of numbers:

  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

The algorithm requires you to sum the individual digits from the original number, and the individual digits of the product of those "every two digits from the right".

So from the right, you sum 3 + (1 + 6) + 2 + (1 + 4) + 3, which gives you 20.

If the number you end up with ends with a zero, which 20 does, the number is valid.

Now, your question hints at you wanting to know how to generate the checksum, well, that's easy, do the following:

  1. Tack on an extra zero, so your number goes from xyxyxyxy to xyxyxyxy0
  2. Calculate the luhn checksum sum for the new number
  3. Take the sum, modulus 10, so you get a single digit from 0 to 10
  4. If the digit is 0, then congratulations, your checksum digit was a zero
  5. Otherwise, calculate 10-digit to get what you need for the last digit, instead of that zero

Example: Number is 12345

  1. Tack on a zero: 123450
  2. Calculate the luhn checksum for 123450, which results in

    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. Take the sum (15), modulus 10, which gives you 5

  4. Digit (5), is not zero
  5. Calculate 10-5, which gives you 5, the last digit should be 5.

So the result is 123455.

这篇关于生成卢恩校验的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆