Есть ли разница в результате этих двух алгоритмов?
Эти два алгоритма используются для проверки действительных номеров участников. Первый - это тот, который мне дал компания, второй - тот, который я разработал, из своих тестов я не вижу никакой разницы между ними функционально,
есть ли случаи, когда кто-нибудь может увидеть, где они будут возвращать разные результаты?
тестовый ввод: 6014355021355010 или же 6014355065446212 или же 6014351000254605
Контрольная цифра рассчитывается с использованием первых 15 цифр следующим образом:
- Суммируйте цифры в четных позициях слева направо
- Умножьте каждую цифру в нечетных позициях (слева направо) на число 2. Если какой-либо результат представляет собой 2 цифры, суммируйте цифры в одну. Суммируйте цифры от каждого умножения в окончательный результат.
- Добавьте окончательные результаты шагов 1 и 2.
- Возьмите последнюю цифру результата из шага 3 и вычтите из 10, чтобы получить контрольную цифру.
- Возьмите последнюю цифру из 16-значного номера и сравните с контрольной цифрой.
- если они равны, это действительно
против
Контрольная цифра вычисляется с использованием целых 16 цифр следующим образом:
- Суммируйте цифры в четных позициях слева направо
- Умножьте каждую цифру в нечетных позициях (слева направо) на число 2. Если какой-либо результат представляет собой 2 цифры, суммируйте цифры в одну. Суммируйте цифры от каждого умножения в окончательный результат.
- Добавьте окончательные результаты шагов 1 и 2.
- Взять окончательный результат и модуль 10
- Если результат равен 0, он действителен
Обновить:
Итак. Я попытался создать оба этих алгоритма в php, второй, который я создал успешно, первый, однако, я не могу приступить к работе.
возможно, я прочитал это неправильно, но вот оригинал, который мне дали для первого алгоритма:
16-значный номер модуля 10 расчет контрольной цифры
Контрольная цифра рассчитывается с использованием первых 15 цифр следующим образом:
1. Суммируйте цифры в четных позициях слева направо
2. Умножьте каждую цифру в нечетных позициях (слева направо) на число 2
Если какой-либо результат состоит из 2 цифр, суммируйте цифры в одну.
Суммируйте цифры от каждого умножения в окончательный результат.
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])
Update2:
Итак, я исправил алгоритм,
Также, я должен отметить, что есть две другие проверки, если (длина числа!= 16) возвращает 1; и if(первые 5 символов!= 601435) возвращают 1;
так есть ли счетчики к этому?
ура, Мэтт
Тест алгоритма [php]
<?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
4 ответа
РЕДАКТИРОВАТЬ: Это доказательство работает только в том случае, если шаги 5 и 6 первого алгоритма являются равной проверки вместо расчета модуля. Равная проверка, по-видимому, подразумевается под первоначальной запиской, упомянутой в комментариях.
РЕДАКТИРОВАТЬ 2: Я думаю, что первый алгоритм должен выглядеть следующим образом. Но вам лучше проверить это, возможно, от того, кто дал вам оригинальное резюме.
- Суммируйте цифры в четных позициях слева направо
- Умножьте каждую цифру в нечетных позициях (слева направо) на число 2. Если какой-либо результат представляет собой 2 цифры, суммируйте цифры в одну. Суммируйте цифры от каждого умножения в окончательный результат.
- Добавьте окончательные результаты шагов 1 и 2.
- Возьмите последнюю цифру результата из шага 3 и вычтите из 10, чтобы получить контрольную цифру.
- Возьмите последнюю цифру 16-значного числа, и если оно совпадает с вычисленной контрольной цифрой, то число является действительным
Для математической проверки того, что оба алгоритма равны, вы можете использовать конгруэнтность.
Скажем a
сумма с шага 3 первого алгоритма, b
является суммой шага 3 второго алгоритма и c
16-ая цифра (контрольная цифра).
Чем разница между a
а также b
в том, что c
добавлен в b
но не для a
, что значит:
a ≡ b - c mod 10
Проверка по первому алгоритму выполняется путем вычитания a
от 10 и проверьте, является ли оно конгруэнтным c
для модуля 10 (для сложения и вычитания не имеет значения, когда выполняется модуль)
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
и это проверка, которая выполняется во втором алгоритме. Таким образом, оба алгоритма возвращают один и тот же результат.
Edit2: Пожалуйста, посмотрите мой другой ответ с контрпримером с правильными алгоритмами.
Изменить: я использовал 15 не 16 чисел во втором алгоритме.
Они не эквивалентны.
Возьмем 383838383838383-6, который действителен для первого алгоритма, но второй алгоритм дает 4 в качестве контрольной цифры!= 0.
Изменить: Суммы 56 для четной части и 48 для нечетной, сумма составляет 104.
У вашего php-кода есть некоторые проблемы.
$check = 10 - $total[1];
действительно только в том случае, если общая сумма представляет собой двузначное число. Потому что ваши номера всегда начинаются с 601435
общая сумма не менее 2 цифр. Но хотя бы 6014359999999990
а также 6014359999999999
будет неверно подтвержден в V2.
Линия 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
возвращает то же значение.
Алгоритмы разные:
принимать 0000000000000257
Исходный алгоритм говорит, что он недействителен: сумма четных цифр равна 2, сумма шансов равна 1 => всего 3. 10-3 = 7. 257 MOD 7 = 5!= 0 => Недействительно
Ваш алгоритм суммирует четные 9, шансы 1 => всего 10. 10 MOD 10 == 0 => Действительный.
Таким образом, они не эквивалентны
QED.:-)