ISBN 从12位转换为13位
我正在尝试从一个12位的ISBN中计算出ISBN-13的校验位,但遇到了一个奇怪的错误。
我的12位ISBN是:978311020318
每个数字交替乘以1或3。
计算方式是这样的:9乘以1,加上7乘以3,加上8乘以1,加上3乘以3,加上1乘以1,加上1乘以3,加上0乘以1,加上2乘以3,加上0乘以1,加上3乘以3,加上1乘以1,加上8乘以3,结果是91。
然后用91除以10,得到的余数是1。
再用10减去1,结果是9,这就是我们的ISBN-13校验位。
这是我目前的代码...
def isbn_check_digit(isbn):
s = 0
for i, d in enumerate(isbn):
if i % 2 == 0:
s += int(d*1)
else:
s += int(d*3)
print(s)
return (10 - (s % 10))
print(isbn_check_digit("978311020318"))
运行后输出了以下内容...
786
1127
1239
1461
1794
2683
7
我把代码拆开来看看发生了什么。
if i % 2 == 0:
s += int(d*1)
print(s)
else:
s += 0
9
17
18
18
18
19
1
乘以1的部分运行得很好,但为什么乘以3的部分会出现奇怪的情况呢?
2 个回答
0
@dustwuff 给出了问题的原因,但另一个解决办法是使用 map
,然后把你的字符串转换成一个列表:
from itertools import izip_longest
def grouper(n, iterable, fillvalue=None):
"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
def isbn_check_digit(isbn):
number = list(map(int, isbn))
check_sum = 0
for i, d in grouper(2, number):
check_sum += i*1 + d*3
return 10 - check_sum % 10
map
会对可迭代的每一个元素应用一个函数。在这个例子中,使用 int
函数可以把你的字符串转换成一个数字列表。
2
因为在计算表达式 int(d * 3)
的时候,d
不是一个数字,而是一个由一个字符组成的字符串,这个字符是一个数字。所以,当你把它“乘”以3时,实际上是把这个字符重复三次:比如说,3
会变成 333
,而不是 9
。
你需要先把字符串转换成整数,然后再乘以3:
int(d) * 3