Существует множество реализаций для проверки контрольных сумм Луна, но очень мало для их создания. Я столкнулся с этим, но в моих тестах он обнаружил, что он глючит, и я не понимаю логики, лежащей в основе дельта-переменной.
Я сделал эту функцию, которая предположительно должна была генерировать контрольные суммы Луна, но по какой-то причине я еще не понял, что сгенерированные контрольные суммы недопустимы в половине случаев.
function Luhn($number, $iterations = 1) { while ($iterations-- >= 1) { $stack = 0; $parity = strlen($number) % 2; $number = str_split($number, 1); foreach ($number as $key => $value) { if ($key % 2 == $parity) { $value *= 2; if ($value > 9) { $value -= 9; } } $stack += $value; } $stack = 10 - $stack % 10; if ($stack == 10) { $stack = 0; } $number[] = $stack; } return implode('', $number); }
Некоторые примеры:
Luhn(3); // 37, invalid Luhn(37); // 372, valid Luhn(372); // 3728, invalid Luhn(3728); // 37283, valid Luhn(37283); // 372837, invalid Luhn(372837); // 3728375, valid
Я проверяю созданные контрольные суммы на этой странице , что я делаю неправильно здесь?
Для справок в будущем здесь приведена рабочая функция.
function Luhn($number, $iterations = 1) { while ($iterations-- >= 1) { $stack = 0; $number = str_split(strrev($number), 1); foreach ($number as $key => $value) { if ($key % 2 == 0) { $value = array_sum(str_split($value * 2, 1)); } $stack += $value; } $stack %= 10; if ($stack != 0) { $stack -= 10; } $number = implode('', array_reverse($number)) . abs($stack); } return $number; }
Я сбросил переменную $ parity, так как для этого она не нужна, и для проверки:
function Luhn_Verify($number, $iterations = 1) { $result = substr($number, 0, - $iterations); if (Luhn($result, $iterations) == $number) { return $result; } return false; }
Изменить : Извините, теперь я понимаю, что у вас уже был почти весь мой ответ, вы просто неправильно определили, какой фактор использовать для какой цифры.
Весь мой ответ теперь можно суммировать с этим единственным предложением:
У вас коэффициент обратный, вы умножаете неправильные цифры на 2 в зависимости от длины номера.
Взгляните на статью Википедии по алгоритму Луна .
Причина, по которой ваша контрольная сумма недействительна в половине случаев, заключается в том, что с вашими проверками половина времени вашего номера имеет нечетное количество цифр, а затем вы удваиваете неправильную цифру.
Для 37283, при подсчете справа, вы получите эту последовательность чисел:
3 * 1 = 3 3 8 * 2 = 16 --> 1 + 6 = 7 2 * 1 = 2 2 7 * 2 = 14 --> 1 + 4 = 5 + 3 * 1 = 3 3 = 20
Алгоритм требует, чтобы вы суммировали отдельные цифры с исходного номера и отдельные цифры продукта этих «каждые две цифры справа».
Итак, справа вы суммируете 3 + (1 + 6) + 2 + (1 + 4) + 3, что дает вам 20.
Если число, в которое вы заканчиваете, заканчивается нулем, что соответствует 20, число действительно.
Теперь, ваш вопрос подсказывает, что вы хотите знать, как сгенерировать контрольную сумму, ну, это легко, сделайте следующее:
Пример: номер 12345
Вычислить контрольную сумму luhn для 123450, что приводит к
0 5 4 3 2 1 1 2 1 2 1 2 <-- factor 0 10 4 6 2 2 <-- product 0 1 0 4 6 2 2 <-- sum these to: 0+1+0+4+6+2+2=15
Возьмите сумму (15), модуль 10, что дает вам 5
Таким образом, результат 123455.
ваш php глючит, он ведет в бесконечный цикл. Это рабочая версия, которую я использую, измененная из вашего кода
функция Luhn ($ number) {
$stack = 0; $number = str_split(strrev($number)); foreach ($number as $key => $value) { if ($key % 2 == 0) { $value = array_sum(str_split($value * 2)); } $stack += $value; } $stack %= 10; if ($stack != 0) { $stack -= 10; $stack = abs($stack); } $number = implode('', array_reverse($number)); $number = $number . strval($stack); return $number;
}
Создайте php и запустите в своем локальном хосте Luhn (xxxxxxxx) для подтверждения.
ПЛОХО
Я буквально не могу поверить, сколько там крахмальных реализаций.
IDAutomation имеет сборку .NET с функцией MOD10 () для создания, но она просто не работает. В Reflector код слишком длинный для того, что он должен делать в любом случае.
ПЛОХО
Этот беспорядок на странице, которая в настоящее время связана с Википедией (!) Для Javascript, имеет несколько реализаций проверки, которые даже не возвращают одно и то же значение при вызове каждого из них.
ХОРОШО
Страница, связанная с страницей Luhn из Википедии, имеет кодировщик Javascript, который, похоже, работает:
// Javascript String.prototype.luhnGet = function() { var luhnArr = [[0,1,2,3,4,5,6,7,8,9],[0,2,4,6,8,1,3,5,7,9]], sum = 0; this.replace(/\D+/g,"").replace(/[\d]/g, function(c, p, o){ sum += luhnArr[ (o.length-p)&1 ][ parseInt(c,10) ] }); return this + ((10 - sum%10)%10); }; alert("54511187504546384725".luhnGet());
ХОРОШО
Эта очень полезная страница EE4253 проверяет контрольную цифру, а также показывает полный расчет и объяснение.
ХОРОШО
Мне нужен код C # и в итоге использовал код кода кода :
// C# public static int GetMod10Digit(string data) { int sum = 0; bool odd = true; for (int i = data.Length - 1; i >= 0; i--) { if (odd == true) { int tSum = Convert.ToInt32(data[i].ToString()) * 2; if (tSum >= 10) { string tData = tSum.ToString(); tSum = Convert.ToInt32(tData[0].ToString()) + Convert.ToInt32(tData[1].ToString()); } sum += tSum; } else sum += Convert.ToInt32(data[i].ToString()); odd = !odd; } int result = (((sum / 10) + 1) * 10) - sum; return result % 10; }
ХОРОШО
Этот код проверки на C #, похоже, работает, если он немного громоздкий. Я просто использовал его, чтобы проверить, что это было правильно.
Теперь существует репозиторий github, основанный на исходном вопросе / ответе. Видеть
https://github.com/xi-project/xi-algorithm
Он также доступен в упаковке
Это функция, которая может вам помочь, она коротка, и все работает отлично.
function isLuhnValid($number) { if (empty($number)) return false; $_j = 0; $_base = str_split($number); $_sum = array_pop($_base); while (($_actual = array_pop($_base)) !== null) { if ($_j % 2 == 0) { $_actual *= 2; if ($_actual > 9) $_actual -= 9; } $_j++; $_sum += $_actual; } return $_sum % 10 === 0; }