Правила расчета контрольной суммы СНИЛС
Допустимые символы - цифры, пробел, дефис.
Проверяется на валидность контрольным числом.
СНИЛС имеет вид "XXX-XXX-XXX YY", где XXX-XXX-XXX - номер, а YY - контрольное число.
Проверка контрольного числа проводится только для номеров больше номера 001-001-998.
(вот это что-то новое – будет уточнено в ОПФР)
Контрольное число СНИЛС рассчитывается следующим образом:
* Каждая цифра СНИЛС умножается на номер своей позиции (позиции отсчитываются с конца);
* Полученные произведения суммируются;
* Если сумма меньше 100, то контрольное число равно самой сумме;
* Если сумма равна 100 или 101, то контрольное число равно 00;
* Если сумма больше 101, то сумма делится нацело на 101 и контрольное число определяется
остатком от деления аналогично предыдущим двум пунктам.
Дополнительная проверка:
* В номере XXX-XXX-XXX не может присутствовать одна и та же цифра три раза подряд. Дефисы при этой проверке игнорируются, т.е. неверными будут все нижеследующие примеры СНИЛСов:
XXX-222-XXX YY
XX2-22X-XXX YY
Пример реализации на языке С++:
AnsiString CheckFields(AnsiString Field)
{ AnsiString S = "", S1;
int i, j, C1, C2, ILS_Num, LastDigit, LastDigitCount;
int ILS14_1[12] = {9, 8, 7, 0, 6, 5, 4, 0, 3, 2, 1, 0};
bool Flag;
S = "068-619-801 04"; // в случае неверного СНИЛС возвращается значение "068-619-801 04”
try {
if(Field.Length() == 14)
{ Flag = true;
i = 0;
C1 = 0;
ILS_Num = 0;
LastDigit = -1;
LastDigitCount = 0;
while(i < 12)
{ switch(i)
{ case 3:
case 7: if(Field[i+1] != '-') Flag = false; break;
case 11: if(Field[i+1] != ' ') Flag = false; break;
default: { if(ILS14_1[i] != 0)
{ C1 = C1 + (int)(Field[i+1] - 0x30) * ILS14_1[i];
ILS_Num = ILS_Num * 10 + (int)(Field[i+1] - 0x30);
if(LastDigit == (int)(Field[i+1] - 0x30))
{ LastDigitCount++;
if(LastDigitCount => 3) Flag = false;
}
else
{ LastDigit = (int)(Field[i+1] - 0x30);
LastDigitCount = 1;
}
}
} break;
}
i++;
}
if(ILS_Num <= 1001998) Flag = false;
if(Flag == true)
{ C1 = C1 - (int)(floor(C1 / 101) * 101);
S1 = (AnsiString)(C1);
switch(S1.Length())
{ case 1: S1 = "0" + S1; break;
case 3: S1 = S1.SubString(2, 2); break;
}
if(S1 == Field.SubString(13, 2)) S = Field;
}
}
}
catch(...)
{
}
return(S);
}