Существует ли встроенная функция или модуль Python, которая будет суммировать цифры, умноженные на их целое значение? - PullRequest
0 голосов
/ 18 февраля 2020

Что мне нужно сделать, это взять 10-значный номер git ISBN и проверить его действительность в соответствии с этим правилом:

Согласно официальному изданию Международного агентства ISBN 2001 года руководство пользователя, [47] ISBN-10 проверка di git (который является последним di git из 10-di git ISBN) должна находиться в диапазоне от 0 до 10 (символ «X» используется для 10 ) и должна быть такой, чтобы сумма десяти цифр, каждая из которых умножалась на ее (целочисленный) вес, уменьшившийся с 10 до 1, была кратна 11.

Другими словами, если число 0-306-40615-2, мне нужно вычислить:

(0 * 10) + (3 * 9) + (0 * 8) + (6 * 7) + (4 * 6) + (0 * 5) + (6 * 4) + (1 * 3) + (5 * 2) + (2 * 1) mod 11

Хотя предложения или советы о том, как написать такую ​​функцию, приветствуются, мой главный вопрос заключается в том, У Python уже есть способ сделать это, возможно, в модуле math.

Это моя попытка, но циклы for не работают, потому что внутренний цикл запускается заново. Плюс это просто кажется грязным!

    checksum = 0
    for digit in isbn:
        for weight in range(10, 0, -1):
            if digit == 'X':
                checksum += 10 * weight
                break
            checksum += int(digit) * weight
            break
    return checksum % 11```

Ответы [ 3 ]

2 голосов
/ 18 февраля 2020

Нет, это слишком определенно c, чтобы быть чем-то в стандартной библиотеке. Это довольно просто написать:

def check_isbn(isbn):
    isbn_digits = (
        10 if ch == 'X' else int(ch)
        for ch in isbn
        if ch.isdigit() or ch == 'X')

    checksum = sum(
        (10 - index) * digit
        for index, digit
        in enumerate(isbn_digits)
    ) % 11

    return checksum % 11 == 0

Мне нравится способ понимания; но императивный способ также должен работать, у вас просто есть ошибки logi c. В частности, вы не хотите повторять все веса для каждого di git. Каждый персонаж имеет ровно один вес, если это ди git, или нет, если это не так. Таким образом, обязательное переписывание будет:

def check_isbn(isbn):
    checksum = 0
    weight = 10
    for ch in isbn:
        if ch == 'X':
            digit = 10
        elif ch.isdigit():
            digit = int(ch)
        else:
            continue
        checksum += digit * weight
        weight -= 1

    return checksum % 11 == 0

РЕДАКТИРОВАТЬ: различные ошибки

1 голос
/ 18 февраля 2020

Вы можете использовать понимание списка и enunerate(), чтобы получить позицию и значение первых 9 цифр. Для каждого di git преобразуйте позицию в ее обратный эквивалент (10-i) и умножьте его на di git. Если вы вычтете сумму этих умножений из 990, вы получите значение, которое сделает общее число кратным 11. Результат можно затем использовать в качестве индекса в строке, содержащей цифры от 0 до 9 и букву X:

isbn     = "0-306-40615-2"
numbers  = [int(n) for n in isbn if n.isdigit()]
check    = "0123456789X"[ (990-sum(n*(10-i) for i,n in enumerate(numbers[:9])))%11]
isValid  = isbn[-1] == check  

print(check) # "2"
0 голосов
/ 18 февраля 2020

Если число 0-306-40615-2, и вам нужно рассчитать, если

(0 * 10) + (3 * 9) + (0 * 8) + (6 * 7) + (4 * 6) + (0 * 5) + (6 * 4) + (1 * 3) + (5 * 2) + (2 * 1)

является кратным 11 , тогда вы можете просто написать простую функцию.

def check_isbn(isbn): #isbn should be type str
    isbn = "".join(isbn.split("-"))
    sum = (int(isbn[0]) * 10) + (int(isbn[1]) * 9) + (int(isbn[2]) * 8) + (int(isbn[3]) * 7) + (int(isbn[4]) * 6) + (int(isbn[5]) * 5) + (int(isbn[6]) * 4) + (int(isbn[7]) * 3) + (int(isbn[8]) * 2) + (int(isbn[9]) * 1)
    return sum % 11 == 0

check_isbn("1416406110")
# False

check_isbn("0-306-40615-2")
# True
...