Reputation: 92581
these two algorithms are used to check valid member numbers the first is the one I was given by the company, the second is one I devised, from my tests I can't see any difference between them functionally,
are there any cases anyone can see where they would return different outputs?
test input: 6014355021355010 or 6014355065446212 or 6014351000254605
The check digit is calculated using the first 15 digits as follows:
- Sum the digits in the even numbered positions from left to right
- Multiply each digit in the odd numbered positions (from left to right) by the number 2. If any results are 2 digits, sum the digits into one. Sum the digits from each multiplication into a final result.
- Add the final results of steps 1 and 2.
- Take the last digit of the result from step 3 and subtract from 10 to give the check digit.
- Take the last digit from the 16 Digit number and compare to the check digit
- if they are equal, it is valid
vs
The check digit is calulated using the whole 16 digits as follows:
- Sum the digits in the even numbered positions from left to right
- Multiply each digit in the odd numbered positions (from left to right) by the number 2. If any results are 2 digits, sum the digits into one. Sum the digits from each multiplication into a final result.
- Add the final results of steps 1 and 2.
- Take the final result and Modulus 10
- If the result is 0, it is valid
possibly i have read this wrong, but, here is the original brief i was given for the first algorithm:
16 digit number modulus 10 check digit calculation
The check digit is calculated using the first 15 digits as follows:
1. Sum the digits in the even numbered positions from left to right
2. Multiply each digit in the odd numbered positions (from left to right) by the number 2
If any results are 2 digits, sum the digits into one.
Sum the digits from each multiplication into a final result.
3. Add the final results of steps 1 and 2.
4. Take the last digit of the result from step 3 and subtract from 10 to give the check digit.
If the result of step 3 is a multiple of 10, then the check digit will be zero.
Example 6014 3590 0000 0928
1.0 0 + 4 + 5 + 0 + 0 + 0 + 9 = 18
2.0 6 * 2 = 12 so 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 The check digit is 10 - 2 = 8
5.0 8 = the 16th digit (601435900000092[8])
also, i should mention, that there are two other checks if(length of number != 16) return 1; and if(first 5 characters != 601435) return 1;
so are there any counters to this?
cheers, Matt
<?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 />';
}
}
if anyone is interested and comments i can post some sample numbers to test against :)
oh and feel free to optimize the code 8D
Upvotes: 3
Views: 518
Reputation: 2710
Your php code has some problems.
$check = 10 - $total[1];
is only valid if the total sum is a 2-digit number. Because your numbers always start with 601435
the total sum has not less than 2 digits. But at least 6014359999999990
and 6014359999999999
would be validated wrong in V2.
The line return $check;
can return 0. That way 6014355021355012
or 6014355021355017
are verified as being valid, while they are not.
I would replace the lines:
$total = str_split($total);
$check = 10 - $total[1];
$check = $check % 10;
if($check == substr($flybuys, 15, 1))
return 0;
else
return $check;
with
return (substr($flybuys, 15, 1) + $total) % 10;
So V1
and V2
returns the same value.
Upvotes: 0
Reputation: 2710
EDIT: This proof only works if the step 5 and 6 of the first algorithm are an equal check instead of a modulus calculation. The equal check seems to be meant by the original brief as mentioned in the comments.
EDIT2: I think the first algorithm should look like this. But you should better verify this, maybe from the one who gave you the original brief.
- Sum the digits in the even numbered positions from left to right
- Multiply each digit in the odd numbered positions (from left to right) by the number 2. If any results are 2 digits, sum the digits into one. Sum the digits from each multiplication into a final result.
- Add the final results of steps 1 and 2.
- Take the last digit of the result from step 3 and substract from 10 to give the check digit.
- Take the last digit of the 16digit-number and if it is the same as the computed check digit the number is valid
To verifiy mathematically that both algorithms are equal you can use congruency.
Let's say a
is the sum from step 3 of the first algorithm, b
is the sum of step 3 of the second algorithm and c
is the 16th digit (the check digit).
Than the difference between a
and b
is that c
is added to b
but not to a
, which means:
a ≡ b - c mod 10
The check from the first algorithm is performed by substracting a
from 10 and check if it is congruent c
for modulus 10. (for addition and substraction it doesn't matter when the modulus is performed)
10 - a ≡ c mod 10
this is equal to:
-a ≡ c mod 10
Now you can substitute a
with the first one, which results in
-(b - c) ≡ c mod 10
this is equal to:
c - b ≡ c mod 10
and this is equal to:
-b ≡ 0 mod 10
b ≡ 0 mod 10
and that is the check, which is performed in the second algorithm. So both algorithms returns the same result.
Upvotes: 6
Reputation: 25632
Edit2: Please see my other answer with a counter example with the correct algorithms.
Edit: I was using 15 not 16 numbers in the second algorithm.
They are not equivalent.
Take 383838383838383-6 which is valid for first algorithm, but the second algorithm gives 4 as the check digit != 0.
Edit: Sums are 56 for the even part and 48 for odd, sum is 104.
Upvotes: 2
Reputation: 25632
The algorithms are different:
Take 0000000000000257
The original algorithm says it's not valid: Sum of even numbered digits is 2, the odds sum is 1 => total of 3. 10-3 = 7. 257 MOD 7 = 5 != 0 => Not valid
You algorithm sums even to 9, odds to 1 => total 10. 10 MOD 10 == 0 => Valid.
So they are not equivalent
qed. :-)
Upvotes: 0