IMEI это международный идентификатор мобильного оборудования. Чтобы при вводе постараться избежать ошибки, к 14 цифрам добавляют 15-ю, так, чтобы при сложении по формуле ниже сумма делилась на 10 без остатка.
x1 + f(x2) + x3 + f(x4) + x5 + f(x6) + x7 + .... + f(x14) + x15 - делится на 10 без остатка.
f(x) — это умножение на 2, и если число становится двузначным, то его цифры суммируются:
0 => 0
1 => 2 (1 * 2 = 2)
2 => 4 (2 * 2 = 4)
3 => 6 (3 * 2 = 6)
4 => 8 (4 * 2 = 8)
5 => 1 (5 * 2 = 10 => 1 + 0 = 1)
6 => 3 (6 * 2 = 12 => 1 + 2 = 3)
7 => 5 (7 * 2 = 14 => 1 + 4 = 5)
8 => 7 (8 * 2 = 16 => 1 + 6 = 7)
9 => 9 (9 * 2 = 18 => 1 + 8 = 9)
По формуле видно, что f(x) применяется к цифрам на нечетных позициях 15-значного IMEI с любого направления.
Ещё стоит добавить, что для 16-значного IMEI такой алгоритм не применим из-за отсутствия последней проверочной цифры.
Реализация на c#:
bool ValidateImeiByLyhn(string imei)
{
if (!imei.All(char.IsDigit))
return false;
if (imei.Length is not 15)
throw new ArgumentOutOfRangeException();
var sum = 0;
for (var i = 0; i < 15; i++)
{
var number = CharUnicodeInfo.GetDecimalDigitValue(imei[i]);
if ((i + 1) % 2 == 0)
sum += number switch
{
0 => 0,
1 => 2,
2 => 4,
3 => 6,
4 => 8,
5 => 1,
6 => 3,
7 => 5,
8 => 7,
9 => 9,
_ => throw new ArgumentOutOfRangeException(imei[i].ToString())
};
else
sum += number;
}
return sum % 10 == 0;
}
Примечание. Алгоритм Лу́на назван в честь его создателя, ученого из IBM Ханса Питера Луна.