Question

CUSIPs are a 9-digit alphanumeric code for uniquely identifying a financial security.

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

They were invented in the 1964, and given the reliability of data transmission in the 60's, the 9th digit is actually a check digit used to confirm the validity of the first 8 characters. Sometimes, even today, you might find reason to want to validate a CUSIP, or perhaps a company or service obnoxiously decides to only transmit the 8-character CUSIP, even though this defeats the purpose of a check digit.

The procedure to generate the check digit is:

  1. Convert non-numeric digits to values according to their ordinal position in the alphabet plus 9 (A=10, B=11,...Z=35) and converting the characters *=36, @=37, #=38.

  2. Multiply every even digit by 2

  3. If the result of the multiplication is a two-digit number, add the digits together. (12 = 1 + 2 = 3)

  4. Get the sum of all values.

  5. Get the floored value of this operation: (10 - (sum modulo 10)) modulo 10.

What is the best/simplest way to get this value in C#?

Was it helpful?

Solution

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();
}

Edit:

.NET Fiddle demonstrating this: https://dotnetfiddle.net/kspQWl

OTHER TIPS

If you pre-compute the values of check digits, and store them in a lookup table, your computation of check digit would become much simpler:

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;
    }
}

With the 2D lookup array in place you can compute check digit in a single line of code:

var checkDigit = (10-(cusip.Select((ch, pos) => Check[ch, pos%2]).Sum()%10))%10;

I see that there is no algo for java so adding it as well:

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);
    }

and some tests:

    @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);
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top