Как создать контрольную цифру CUSIP в C#
CUSIP - это 9-значный буквенно-цифровой код для уникальной идентификации финансовой безопасности.
https://en.wikipedia.org/wiki/CUSIP
Они были изобретены в 1964 году, и, учитывая надежность передачи данных в 60-х годах, 9-ая цифра фактически является контрольной цифрой, используемой для подтверждения достоверности первых 8 символов. Иногда, даже сегодня, вы можете найти причину для проверки CUSIP, или, возможно, компания или служба несправедливо решат передать только 8-символьный CUSIP, даже если это противоречит цели проверки цифры.
Процедура создания контрольной цифры:
Преобразование нечисловых цифр в значения в соответствии с их порядковым положением в алфавите плюс 9 (A=10, B=11,...Z=35) и преобразование символов *=36, @=37, #=38.
Умножьте каждую четную цифру на 2
Если результатом умножения является двузначное число, сложите цифры вместе. (12 = 1 + 2 = 3)
Получить сумму всех значений.
Получить итоговое значение этой операции: (10 - (сумма по модулю 10)) по модулю 10.
Каков наилучший / самый простой способ получить это значение в C#?
3 ответа
Автоответчик, потому что я вчера гуглял по этому поводу и хочу кого-нибудь спасти. Я хочу услышать больше ответов или отзывов.
public string GenerateCheckDigit(string cusip)
{
int sum = 0;
char[] digits = cusip.ToUpper().ToCharArray();
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#";
for (int i = 0; i < digits.Length; i++)
{
int val;
if (!int.TryParse(digits[i].ToString(), out val))
val = alphabet.IndexOf(digits[i]) + 10;
if ((i % 2) != 0)
val *= 2;
val = (val % 10) + (val / 10);
sum += val;
}
int check = (10 - (sum % 10)) % 10;
return check.ToString();
}
Редактировать:
.NET Fiddle демонстрирует это: https://dotnetfiddle.net/kspQWl
Я вижу, что для java нет алгоритма, поэтому добавляю его:
String generateCusipCheckDigit(String cusip) {
final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#";
int sum = 0;
int value = 0;
char[] cusipChars = cusip.toUpperCase().toCharArray();
for (int i = 0; i < cusipChars.length; i++) {
char actualChar = cusipChars[i];
if (Character.isDigit(actualChar)) {
value = Integer.parseInt(String.valueOf(actualChar));
} else if (Character.isAlphabetic(actualChar)){
value = alphabet.indexOf(actualChar) + 10;
} else if (cusipChars[i] == '*'){
value = 36;
} else if (cusipChars[i] == '@'){
value = 37;
} else if (cusipChars[i] == '#'){
value = 38;
}
if ((i % 2) != 0){
value *= 2;
}
value = (value % 10) + (value / 10);
sum += value;
}
int check = (10 - (sum % 10)) % 10;
return String.valueOf(check);
}
и несколько тестов:
@Test
void checkDigitTest1(){
String actual = generator.generateCusipCheckDigit("925524BF");
Assertions.assertEquals("6", actual);
}
@Test
void checkDigitTest2(){
String actual = generator.generateCusipCheckDigit("90284B96");
Assertions.assertEquals("2", actual);
}
@Test
void checkDigitTest3(){
String actual = generator.generateCusipCheckDigit("90284B97");
Assertions.assertEquals("0", actual);
}
Если вы предварительно вычислите значения контрольных цифр и сохраните их в справочной таблице, вычисление контрольной цифры станет намного проще:
private static readonly int[,] Check = new int[128, 2];
static CusipCheckSum() {
var cusipChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#";
for (var i = 0 ; i != cusipChars.Length ; i++) {
Check[cusipChars[i], 0] = i%10 + i/10;
Check[cusipChars[i], 1] = 2*i%10 + 2*i/10;
}
}
С помощью двумерного поискового массива вы можете вычислить контрольную цифру в одной строке кода:
var checkDigit = (10-(cusip.Select((ch, pos) => Check[ch, pos%2]).Sum()%10))%10;