这两个算法用于检查有效的会员编号,第一个是我公司给出的,第二个是我设计的,从我的测试我看不出它们之间的功能,
有没有人能看到他们会在哪里返回不同的输出?
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 so 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])
另外,我应该提一下,如果(长度数!= 16)返回1,还有另外两个检查; 如果(前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 />';
}
}
Run Code Online (Sandbox Code Playgroud)
如果有人有兴趣和评论我可以发布一些样本数来测试:)
哦,并随意优化代码8D
编辑:此证明仅在第一算法的步骤5和6是等同检查而不是模数计算时才有效.平等检查似乎是评论中提到的原始简报.
EDIT2:我认为第一个算法应该是这样的.但你应该更好地验证这一点,也许应该是给你原始简报的人.
- 从左到右对偶数位置的数字求和
- 将奇数位置(从左到右)中的每个数字乘以数字2.如果任何结果是2位数,则将数字加总为1.将每次乘法的数字相加到最终结果中.
- 添加步骤1和2的最终结果.
- 取第3步结果的最后一位数,从10减去得到校验位.
- 取16位数的最后一位,如果它与计算的校验位相同,则该数字有效
为了在数学上验证两种算法是相等的,您可以使用一致性.
假设a是第一算法b的步骤3的总和,是第二算法的步骤3的总和,并且c是第16位(校验位).
比之间的差a,并b是c被添加到b但不a,这意味着:
a ? b - c mod 10
Run Code Online (Sandbox Code Playgroud)
来自第一算法的检查通过a从10 减去并检查它是否与c模数10 一致来执行.(对于加法和减法,当执行模数时无关紧要)
10 - a ? c mod 10
Run Code Online (Sandbox Code Playgroud)
这相当于:
-a ? c mod 10
Run Code Online (Sandbox Code Playgroud)
现在你可以a用第一个替换,结果是
-(b - c) ? c mod 10
Run Code Online (Sandbox Code Playgroud)
这相当于:
c - b ? c mod 10
Run Code Online (Sandbox Code Playgroud)
这相当于:
-b ? 0 mod 10
b ? 0 mod 10
Run Code Online (Sandbox Code Playgroud)
这是检查,在第二个算法中执行.因此两种算法都返回相同的结果.