计算ISIN校验和

4

你好,我知道这个问题在这里有很多讨论,但是我没能找到一个足够详细的答案,Wikipedia上有两个ISIN的例子以及它们checksum(校验和)的计算方法。

我困惑的计算部分是:

乘以包含最右边字符的组

我理解这句话的方式是:

  • 从右向左迭代每个字符
  • 一旦你遇到一个字符而不是数字,请记录其位置
    • 如果该位置是偶数,则将所有数字值加倍在偶数位置
    • 如果该位置为奇数,则将所有数字值加倍在奇数位置

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

  • 每个ISIN都以两个字符的国家代码开头,因此最右侧字符的位置始终是第一个字符
  • 如果省略前两个字符,则没有说明如何处理全部由数字组成(除了前两个字符)的ISIN

注意

isin.org对验证ISIN的信息甚至更少,他们甚至使用与Wikipedia相同的例子。

1个回答

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

因此,在这个小例子中,第四步的结果为:8, 0, 5

Python中一个最简单的可行实现可能如下:

import string
isin = 'US4581401001'

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.ascii_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)

在ISIN数据库https://www.isin.net/isin-directory/中,对于US0358140123有些困难,貌似该算法输出了9(?)。 - Sam Ginrich
1
@SamGinrich 看起来该特定ISIN甚至根据其他在线验证器也无效。例如,请参见https://www.isincheck.com/?isin=US0358140123,或https://www.isindb.com/validate-isin/。 - Jir
1
有用的链接!US0358140129已被接受,谢谢。 - Sam Ginrich

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接