4

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 - ( sum modulo 10)) modulo 10。

在 C# 中获得此值的最佳/最简单方法是什么?

4

3 回答 3

11

自我回答,因为我昨天在谷歌上搜索这个,想救人一些时间。不过,我确实想听到更多的答案或反馈。

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

于 2014-03-06T17:08:55.437 回答
4

如果您预先计算校验位的值,并将它们存储在查找表中,校验位的计算将变得更加简单:

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;
于 2015-11-11T16:11:09.857 回答
1

我看到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);
    }
于 2021-12-13T08:27:11.873 回答