【问题标题】:Calculating ISIN checksum计算 ISIN 校验和
【发布时间】:2017-09-05 18:27:31
【问题描述】:

您好,我知道这里可能对此有疑问,但我无法找到足够详细的答案,Wikipedia 有两个 ISIN 示例以及它们的校验和是如何计算的。

我正在努力解决的计算部分是

乘以包含最右边字符的组

我对这句话的理解是:

  • 从右到左遍历每个字符
  • 一旦你偶然发现一个字符而不是数字记录它的位置
    • 如果位置是even 数字,则将even 位置中的所有数值加倍
    • 如果位置是odd 数字,则将odd 位置中的所有数值加倍

我的理解肯定是错误的,因为至少有两个问题:

  • 每个 ISIN 都以两个字符的国家/地区代码开头,因此最右边字符的位置始终是第一个字符
  • 如果省略前两个字符,则无法解释如何处理由所有数字组成的 ISIN(前两个字符除外)

注意

isin.org 包含的关于验证 ISIN 的信息更少,他们甚至使用与维基百科相同的示例。

【问题讨论】:

    标签: checksum


    【解决方案1】:

    我同意你的看法;维基百科上的定义不是我见过的最清楚的。

    在两个示例之前有一段文字解释了何时应该使用一种或另一种算法:

    由于 NSIN 元素可以是任何字母数字序列(9 个字符),因此奇数个字母将产生偶数个数字,而偶数个字母将产生奇数个数字。对于奇数位数,使用第一个示例中的方法。对于偶数位数,使用第二个例子中的方法

    NSIN 与 ISIN 相同,除了前两个字母和最后一个数字;因此,如果 ISIN 为 US0378331005,则 NSIN 为 037833100。 因此,如果要验证US0378331005 的校验和数字,则必须使用“第一个算法”,因为 NSIN 中有 9 位数字。相反,如果您想检查AU0000XVGZA3,您将使用“第二种算法”,因为 NSIN 包含 4 位数字。

    至于“第一”和“第二”算法,它们是相同的,唯一的例外是前者将奇数组乘以 2,而后者将乘以 2偶数组。

    现在,好消息是,您可以摆脱这种过于复杂的算法。

    您可以改为:

    1. 输入 ISIN,除了最后一位(您需要验证)
    2. 将所有字母转换为数字,从而获得数字列表
    3. 反转数字列表
    4. 如果结果 >= 10,则奇数位置的所有数字都加倍,并且它们的数字再次相加
    5. 偶数位置的所有数字均按原样获取
    6. 对所有数字求和,取模,从 0 中减去结果,取绝对值

    唯一棘手的步骤是#4。让我们用一个小例子来澄清它。 假设奇数位的数字是4, 0, 7

    你将它们加倍并得到:8, 0, 14

    8 不是 >= 10,所以我们照原样取它。 0 同上。14 >= 10,所以我们再次对其数字求和:1+4=5

    因此,此小示例中第 4 步的结果是:8, 0, 5

    在 Python 中的最小工作实现可能如下所示:

    import string
    
    def digit_sum(n):
        return (n // 10) + (n % 10)
    
    alphabet = {letter: value for (value, letter) in
                enumerate(''.join(str(n) for n in range(10)) + string.uppercase)}
    
    isin_to_digits = ''.join(str(d) for d in (alphabet[v] for v in isin[:-1]))
    isin_sum = 0
    for (i, c) in enumerate(reversed(isin_to_digits), 1):
        if i % 2 == 1:
            isin_sum += digit_sum(2*int(c))
        else:
            isin_sum += int(c)
    
    checksum_digit = abs(- isin_sum % 10)
    
    assert int(isin[-1]) == checksum_digit
    

    或者,更挤,只是为了功能的乐趣:

    checksum_digit = abs( - sum(digit_sum(2*int(c)) if i % 2 == 1 else int(c)
        for (i, c) in enumerate(
        reversed(''.join(str(d) for d in (alphabet[v] for v in isin[:-1]))), 1)) % 10)
    

    【讨论】:

      猜你喜欢
      • 2010-12-01
      • 2015-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-11
      • 2021-05-08
      • 2015-01-04
      相关资源
      最近更新 更多