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 преобразует вашу строку в список чисел.

Другие вопросы по тегам