ISBN от 12 до 13 цифр
Я пытаюсь вернуть контрольный номер ISBN-13 из 12-значного номера ISBN, но обнаружил странную ошибку.
Возьмите следующее как мой 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 ответа
Потому что в то время, когда выражение int(d * 3)
оценивается, d
это не число - это строка, состоящая из одного символа, который является цифрой. В результате "умножение" на 3 повторит цифру три раза: например, 3
превратится в 333
, скорее, чем 9
,
Вы хотите умножить на 3 после преобразования строки в целое число:
int(d) * 3
@ 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
преобразует вашу строку в список чисел.