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 - (sum modulo 10)) modulo 10。
在 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();
}
编辑:
.NET Fiddle 演示了这一点:https://dotnetfiddle.net/kspQWl
如果你预先计算出校验位的值,并将它们存储在查找表中,那么校验位的计算将变得更加简单:
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;
}
}
使用 2D 查找数组后,您可以在一行代码中计算校验位:
var checkDigit = (10-(cusip.Select((ch, pos) => Check[ch, pos%2]).Sum()%10))%10;
我发现 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);
}
使用内置函数检查 SecuMas(一个 Python 包)以获取安全标识符。
参考下面的代码。要生成 CUSIP 校验位,请输入 8 个字符串。
import SecuMas
print (SecuMas.cusip.get_check_digit('H4209710'))