Как создать контрольную цифру CUSIP в C#

CUSIP - это 9-значный буквенно-цифровой код для уникальной идентификации финансовой безопасности.

https://en.wikipedia.org/wiki/CUSIP

Они были изобретены в 1964 году, и, учитывая надежность передачи данных в 60-х годах, 9-ая цифра фактически является контрольной цифрой, используемой для подтверждения достоверности первых 8 символов. Иногда, даже сегодня, вы можете найти причину для проверки CUSIP, или, возможно, компания или служба несправедливо решат передать только 8-символьный CUSIP, даже если это противоречит цели проверки цифры.

Процедура создания контрольной цифры:

  1. Преобразование нечисловых цифр в значения в соответствии с их порядковым положением в алфавите плюс 9 (A=10, B=11,...Z=35) и преобразование символов *=36, @=37, #=38.

  2. Умножьте каждую четную цифру на 2

  3. Если результатом умножения является двузначное число, сложите цифры вместе. (12 = 1 + 2 = 3)

  4. Получить сумму всех значений.

  5. Получить итоговое значение этой операции: (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;
Другие вопросы по тегам