有很多实现的用于验证卢恩校验但对他们产生非常少。 我已经遇到这个然而,在我的测试中,它揭示了要马车,我不明白增量变量背后的逻辑。
我做了推测应该产生卢恩校验这个功能,但由于某种原因,我还没有认识到所产生的校验和的无效时间的一半。
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;
}
编辑 :对不起,我现在认识到,你就已经,您刚刚正确确定将使用为其数字哪种因素几乎我的整个的答案。
我的整个现在答案可以概括这个简单的句子:
你有逆转的因素,你被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呢,这个数字是有效的。
现在,你的问题暗示你想知道如何生成校验和,那么,这很容易,做到以下几点:
- 在一个零粘性,所以你的电话号码去从xyxyxyxy到xyxyxyxy0
- 计算LUHN校验总和的新号码
- 就拿总和,模数10,所以你得到一个数字从0到10
- 如果数字是0,那么恭喜你,你的校验位是零
- 否则,计算出的10位获得您所需要的最后一个数字,而不是说零
例如:编号为12345
- 钉在零:123450
计算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
就拿总和(15),模数10,它给你5
- 数字(5),是不为零
- 计算10-5,它给你5,最后一个数字应为5。
所以结果是123455。
你的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)确认运行。
坏
我简直不敢相信有多少糟糕的实现也有在那里。
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#中验证代码似乎工作,如果有点笨拙。 我只是用它来检查以上是正确的。
现在有在原有基础上提问/回答一个GitHub库。 看到
https://github.com/xi-project/xi-algorithm
它也可在packagist
这是一个功能,可以帮助你,因为它很短,它工作得很好。
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;
}