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:
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.
Multiply every even digit by 2
If the result of the multiplication is a two-digit number, add the digits together. (12 = 1 + 2 = 3)
Get the sum of all values.
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#?
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
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With