这两种算法用于检查有效的成员编号 第一个是我公司给的, 第二个是我设计的,从我的测试中我看不出它们在功能上有什么区别,
有没有人能看到他们会在哪里返回不同的输出?
test input: 6014355021355010 or 6014355065446212 or 6014351000254605
校验位使用前15位数字计算如下:
- 从左到右对偶数位置的数字求和
- 将奇数位置的每个数字相乘(从左到右) 右)由数字2.如果有任何结果 是2位数,将数字加总为1。 对每个数字求和 乘以最终结果。
- 添加步骤1和2的最终结果。
- 从步骤3中取结果的最后一位数,然后从10减去 给出校验位。
- 从16位数字中取最后一位数字并与校验位
进行比较- 如果相等,则有效
醇>
VS
校验位使用整数16位数进行计算,如下所示:
- 从左到右对偶数位置的数字求和
- 将奇数位置的每个数字相乘(从左到右) 右)由数字2.如果有任何结果 是2位数,将数字加总为1。 对每个数字求和 乘以最终结果。
- 添加步骤1和2的最终结果。
- 取最终结果和模数10
- 如果结果为0,则有效
醇>
<小时/> 更新:
可能我读过这个错误,但是,这是我给第一个算法的原始简介:
16位数模数10校验位计算
校验位使用前15位数字计算如下:
1. 从左到右对偶数位置的数字求和
2. 将奇数位置(从左到右)的每个数字乘以数字2 如果任何结果是2位数,则将数字加总为1 将每次乘法的数字相加到最终结果中
3. 添加步骤1和2的最终结果
4. 取第3步结果的最后一位数,并从10减去得到校验位。
如果步骤3的结果是10的倍数,则校验位将为零
示例 6014 3590 0000 0928
1.0 0 + 4 + 5 + 0 + 0 + 0 + 9 = 18
2.0 6 * 2 = 12 所以 1 + 2 = 3
2.1 1 * 2 = 2
2.2 3 * 2 = 6
2.3 9 * 2 = 18 所以 1 + 8 = 9
2.4 0 * 2 = 0
2.5 0 * 2 = 0
2.6 0 * 2 = 0
2.7 2 * 2 = 4
2.8 3 + 2 + 6 + 9 + 0 + 0 + 0 + 4 = 24
3.0 18 + 24 = 42
4.0 校验位为10 - 2 = 8
5.0 8 =第16位(601435900000092 [8])
<小时/> 更新2:
另外,我应该提一下,还有另外两项检查 if(数量的长度!= 16) 返回1; 和 if(前5个字符!= 601435) 返回1;
那么有什么反击吗?
欢呼声, 马特
<?php
$file = file_get_contents('fb.csv');
$numbers = explode("\n", $file);
function validate_flybuys($number) {
$r = array ('o' => '0', 'i' => '1', 'l' => '1', 'e' => '3', ' ' => '');
$flybuys = trim(strtolower($number));
$flybuys = str_replace(array_keys($r), $r, $flybuys);
if('601435' != substr($flybuys, 0, 6) || strlen($flybuys) != 16)
return 1;
$evens = 0;
$odds = '';
for($i = 0; $i <= 15; $i+=2) {
$odds .= $flybuys[$i];
$evens += $flybuys[$i+1];
}
$odds = str_split($odds);
foreach($odds as &$odd) {
$odd = $odd*2;
if($odd >= 10) {
$odd = str_split($odd);
$odd = $odd[0] + $odd[1];
}
}
return (array_sum($odds)+$evens) % 10;
}
function validate_flybuys2($number) {
$r = array ('o' => '0', 'i' => '1', 'l' => '1', 'e' => '3', ' ' => '');
$flybuys = trim(strtolower($number));
$flybuys = str_replace(array_keys($r), $r, $flybuys);
if('601435' != substr($flybuys, 0, 6) || strlen($flybuys) != 16)
return 1;
$evens = 0;
$odds = '';
for($i = 0; $i <= 14; $i+=2) {
$odds .= $flybuys[$i];
if($i != 14)
$evens += $flybuys[$i+1];
}
$odds = str_split($odds);
foreach($odds as &$odd) {
$odd = $odd*2;
if($odd >= 10) {
$odd = str_split($odd);
$odd = $odd[0] + $odd[1];
}
}
$total = (array_sum($odds))+$evens;
$total = str_split($total);
$check = 10 - $total[1];
$check = $check % 10;
if($check == substr($flybuys, 15, 1))
return 0;
else
return $check;
}
foreach($numbers as $number) {
$valid = validate_flybuys($number);
$valid2 = validate_flybuys2($number);
if($valid != $valid2 || $valid != 0) {
echo '<hr />';
echo 'NUMBER: '.$number.'<br />';
echo 'V1: '.$valid.'<br />';
echo 'V2: '.$valid2.'<br />';
}
}
如果有人有兴趣和评论我可以张贴一些样本数来测试:) 哦,随意优化代码8D
答案 0 :(得分:6)
编辑:此证明仅在第一算法的步骤5和6是相等检查而不是模数计算时才有效。平等检查似乎是评论中提到的原始简报。
EDIT2:我认为第一个算法应该是这样的。但你应该更好地验证这一点,也许应该是给你原始简报的人。
- 从左到右对偶数位置的数字求和
- 将奇数位置(从左到右)中的每个数字乘以数字2.如果任何结果是2位数,则将数字相加为1。将每次乘法的数字加总成最终结果。
- 添加步骤1和2的最终结果。
- 取第3步结果的最后一位数,并从10减去得到校验位。
- 取16位数的最后一位数,如果它与计算的校验位相同,则该数字有效
醇>
为了在数学上验证两种算法是相等的,您可以使用congruency。
假设a
是第一个算法第3步的总和,b
是第二个算法的第3步的总和,c
是第16个数字(校验位) )。
a
与b
之间的差异是c
已添加到b
但未添加到a
,这意味着:
a ≡ b - c mod 10
来自第一个算法的检查是通过从10中减去a
来执行的,并检查模数10是否为全等c
。对于加法和减法,当执行模数时无关紧要)
10 - a ≡ c mod 10
这等于:
-a ≡ c mod 10
现在,您可以将a
替换为第一个,结果为
-(b - c) ≡ c mod 10
这等于:
c - b ≡ c mod 10
这等于:
-b ≡ 0 mod 10
b ≡ 0 mod 10
,这是检查,在第二个算法中执行。因此两种算法都返回相同的结果。
答案 1 :(得分:2)
Edit2:请使用正确算法的计数器示例查看我的其他答案。
编辑:我在第二种算法中使用了15个而不是16个数字。
它们不等同。
取383838383838383-6这对第一个算法有效,但第二个算法给出4作为校验位!= 0。
编辑:偶数部分为56,奇数为48,总和为104。
答案 2 :(得分:0)
算法不同:
选择0000000000000257
原始算法表明它无效:偶数数字的总和为2,赔率总和为1 =&gt;总计3. 10-3 = 7. 257 MOD 7 = 5!= 0 =&gt;无效
你的算法总和甚至为9,赔率为1 =&gt;总计10. 10 MOD 10 == 0 =&gt;有效的。
所以他们不等同
QED。 : - )
答案 3 :(得分:0)
您的PHP代码存在一些问题。
$check = 10 - $total[1];
仅在总和为2位数时有效。由于您的号码始终以601435
开头,因此总金额不少于2位数。但在V2中至少会验证6014359999999990
和6014359999999999
错误。
行return $check;
可以返回0.这样6014355021355012
或6014355021355017
被验证为有效,而不是。
我会替换这些行:
$total = str_split($total);
$check = 10 - $total[1];
$check = $check % 10;
if($check == substr($flybuys, 15, 1))
return 0;
else
return $check;
带
return (substr($flybuys, 15, 1) + $total) % 10;
因此V1
和V2
会返回相同的值。