Есть ли разница в результате этих двух алгоритмов?

Эти два алгоритма используются для проверки действительных номеров участников. Первый - это тот, который мне дал компания, второй - тот, который я разработал, из своих тестов я не вижу никакой разницы между ними функционально,

есть ли случаи, когда кто-нибудь может увидеть, где они будут возвращать разные результаты?

тестовый ввод: 
6014355021355010
или же
6014355065446212
или же
6014351000254605

Контрольная цифра рассчитывается с использованием первых 15 цифр следующим образом:

  1. Суммируйте цифры в четных позициях слева направо
  2. Умножьте каждую цифру в нечетных позициях (слева направо) на число 2. Если какой-либо результат представляет собой 2 цифры, суммируйте цифры в одну. Суммируйте цифры от каждого умножения в окончательный результат.
  3. Добавьте окончательные результаты шагов 1 и 2.
  4. Возьмите последнюю цифру результата из шага 3 и вычтите из 10, чтобы получить контрольную цифру.
  5. Возьмите последнюю цифру из 16-значного номера и сравните с контрольной цифрой.
  6. если они равны, это действительно

против

Контрольная цифра вычисляется с использованием целых 16 цифр следующим образом:

  1. Суммируйте цифры в четных позициях слева направо
  2. Умножьте каждую цифру в нечетных позициях (слева направо) на число 2. Если какой-либо результат представляет собой 2 цифры, суммируйте цифры в одну. Суммируйте цифры от каждого умножения в окончательный результат.
  3. Добавьте окончательные результаты шагов 1 и 2.
  4. Взять окончательный результат и модуль 10
  5. Если результат равен 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: Я думаю, что первый алгоритм должен выглядеть следующим образом. Но вам лучше проверить это, возможно, от того, кто дал вам оригинальное резюме.

  1. Суммируйте цифры в четных позициях слева направо
  2. Умножьте каждую цифру в нечетных позициях (слева направо) на число 2. Если какой-либо результат представляет собой 2 цифры, суммируйте цифры в одну. Суммируйте цифры от каждого умножения в окончательный результат.
  3. Добавьте окончательные результаты шагов 1 и 2.
  4. Возьмите последнюю цифру результата из шага 3 и вычтите из 10, чтобы получить контрольную цифру.
  5. Возьмите последнюю цифру 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.:-)

Другие вопросы по тегам