我知道这里有可能有问题,但我无法找到足够详细的答案,Wikipedia有两个ISIN的例子,他们的校验和是如何计算的。
我正在努力的计算部分是
将包含最右边字符的组相乘
我理解这句话的方式是:
even
数字加倍even
位置的所有数值
如果位置是odd
数字加倍odd
位置的所有数值我的理解一定是错的,因为至少有两个问题:
isin.org包含有关验证ISIN的更少信息,它们甚至使用与维基百科相同的示例。
我同意你的观点,维基百科的定义并不是我所见过的最清晰的。
在两个示例之前有一段文本,当应该使用一个或另一个算法时,它会丢弃。引用:
由于NSIN元素可以是任何字母数字序列(9个字符),因此奇数个字母将产生偶数个数字,偶数个字母将产生奇数个数字。对于奇数个数字,使用第一个示例中的方法。对于偶数位数,使用第二示例中的方法
因此,如果要验证US0378331005
的校验和数字,则必须使用“第一算法”,因为ISIN中有2个字母。相反,如果你想检查AU0000XVGZA3
,你将使用“第二算法”,因为ISIN包含7个字母。
至于“第一”和“第二”算法,它们是相同的,唯一的例外是在前者中你将乘以奇数位组2,而在后者中你将乘以2的组。偶数。
现在,好消息是,如果没有这种过于复杂的算法,你就可以逃脱。
你可以改为:
唯一棘手的步骤是#4。让我们用一个小例子来澄清它。假设奇数位的数字是4, 0, 7
。
你会加倍他们得到:8, 0, 14
。
8不是> = 10,所以我们照原样。同上为0.14> = 0,所以我们再次求和它的数字: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)