Как преобразовать входную строку в список чисел с плавающей запятой python - PullRequest
0 голосов
/ 17 июня 2020

Я делаю программу, которая проверяет, действительна ли кредитная карта. Я написал код, который проверяет, проходит ли номер карты алгоритм Луна, но я упустил одну деталь в начале, а именно то, что вы не можете напрямую преобразовать список строк в числа с плавающей запятой. Я понял это только тогда, когда начал тестировать свою программу, используя реальные номера карт и получая ValueError. Есть ли какое-либо решение для этого без повторной реализации моего решения.

def card(digits):
    digits = [int(i) for i in digits]
    digits = [float(x) for x in (digits)]
    print(digits)

    #checks card length and checksum
    if len(digits) == 13:
        even_digits = [digits[-2] * 2, digits[-4] * 2, digits[-6] * 2, digits[-8] * 2, digits[-10] * 2, digits[-12] * 2]
        odd_digits = [digits[-1], digits[-3], digits[-5], digits[-7], digits[-9], digits[-11], digits[-13]]
        all_sum = sum(odd_digits) + sum(even_digits)

        if all_sum % 10 == 0:
            print("checksum passed")

            if digits[0] == 4:
                print("VISA")
        else:
            print("INVALID")

    elif len(digits) == 15:
        even_digits = [digits[-2] * 2, digits[-4] * 2, digits[-6] * 2, digits[-8] * 2, digits[-10] * 2, digits[-12] * 2, digits[-14] * 2]
        odd_digits = [digits[-1], digits[-3], digits[-5], digits[-7], digits[-9], digits[-11], digits[-13], digits[-15]]
        all_sum = sum(odd_digits) + sum(even_digits)

        if all_sum % 10 == 0:
            print("checksum passed")

            if digits[0] == 3 and digits[1] == 7 or 4 :
                print("AMEX")        
        else:
            print("INVALID")

    elif len(digits) == 16:
        even_digits = [digits[-2] * 2, digits[-4] * 2, digits[-6] * 2, digits[-8] * 2, digits[-10] * 2, digits[-12] * 2, digits[-14] * 2, digits[-16] * 2]
        odd_digits = [digits[-1], digits[-3], digits[-5], digits[-7], digits[-9], digits[-11], digits[-13], digits[-15]]
        all_sum = sum(odd_digits) + sum(even_digits)

        if all_sum % 10 == 0:
            print("checksum passed")

            if digits[0] == 4:
                print("VISA")

            elif digits[0] == 5 and digits[1] == 1 or 2 or 3 or 4 or 5:
                print("MASTERCARD")
        else:
            print("INVAlID")

    else:
        print("INVALID")



card(input("Number: "))

Ответы [ 4 ]

0 голосов
/ 18 июня 2020

Благодаря Green Cloak Guy мне удалось решить проблему. Ниже представлено обновленное решение, если кто-то захочет его попробовать.

#helper method to check if an object can be casted to another type #thanks to Green Cloak Guy

def is_castable(obj, T): try: T(obj) return True except ValueError: return False

def card(digits): digits = [float(x) for x in digits if is_castable(x, float)]

#checks card length and performs checksum(Luhn's algoritm)
if len(digits) == 13:
    even_digits = [digits[-2] * 2, digits[-4] * 2, digits[-6] * 2, digits[-8] * 2, digits[-10] * 2, digits[-12] * 2] #multipies even digits of the card by 2
    #adds digits of a number greater than 10
    #this is necessary because the checksum requires to add each digit of the even digits
    for even_digit in even_digits:
        if even_digit >= 10:
            ind = even_digits.index(even_digit)
            first_digit = int(even_digit / 10)
            last_digit = even_digit % 10
            even_digits[ind] = float(first_digit + last_digit)

    odd_digits = [digits[-1], digits[-3], digits[-5], digits[-7], digits[-9], digits[-11], digits[-13]]
    all_sum = sum(odd_digits) + sum(even_digits)

    if all_sum % 10 == 0:
        #After passing the checksum if the first digit is 4 then it is a visa card
        if digits[0] == 4:
            print("VISA")            
    else:
        print("INVALID")


elif len(digits) == 15:
    even_digits = [digits[-2] * 2, digits[-4] * 2, digits[-6] * 2, digits[-8] * 2, digits[-10] * 2, digits[-12] * 2, digits[-14] * 2]
    #adds digits of a number greater than 10
    #this is necessary because the checksum requires to add each digit of the even digits
    for even_digit in even_digits:
        if even_digit >= 10:
            ind = even_digits.index(even_digit)
            first_digit = int(even_digit / 10)
            last_digit = even_digit % 10
            even_digits[ind] = float(first_digit + last_digit)        
    odd_digits = [digits[-1], digits[-3], digits[-5], digits[-7], digits[-9], digits[-11], digits[-13], digits[-15]]
    all_sum = sum(odd_digits) + sum(even_digits)

    if all_sum % 10 == 0:
        #After passing the checksum if the card starts with 34 or 37 then it is an amex card
        if digits[0] == 3 and digits[1] == 7 or 4 :
            print("AMEX")            
    else:
        print("INVALID")


elif len(digits) == 16:
    even_digits = [digits[-2] * 2, digits[-4] * 2, digits[-6] * 2, digits[-8] * 2, digits[-10] * 2, digits[-12] * 2, digits[-14] * 2, digits[-16] * 2]
    #adds digits of a number greater than 10
    #this is necessary because the checksum requires to add each digit of the even digits
    for even_digit in even_digits:
        if even_digit >= 10:
            ind = even_digits.index(even_digit)
            first_digit = int(even_digit / 10)
            last_digit = even_digit % 10
            even_digits[ind] = float(first_digit + last_digit)
    odd_digits = [digits[-1], digits[-3], digits[-5], digits[-7], digits[-9], digits[-11], digits[-13], digits[-15]]
    all_sum = sum(odd_digits) + sum(even_digits)

    if all_sum % 10 == 0:
        #After passing the checksum if the first digit is 4 then it is a visa card
        if digits[0] == 4:
            print("VISA")
        #After passing the checksum if card starts with 51-5 then it is a mastercard
        elif digits[0] == 5 and digits[1] == 1 or 2 or 3 or 4 or 5:
            print("MASTERCARD")        
    else:
        print("INVAlID")

else:
    print("INVALID")

карточка (ввод ("Число:")) `

0 голосов
/ 17 июня 2020

вы не можете напрямую преобразовать список строк в числа с плавающей запятой.

Я не знаю, что, по вашему мнению, означает «список строк», но вы можете преобразовать строки в целые числа или с плавающей точкой согласно , выглядит ли текст в строке как действительное целое число или число с плавающей запятой . Строка типа "3" преобразуется в целое число 3 или значение с плавающей запятой 3.0; строка типа "apple" не преобразуется ни во что numeri c, потому что не существует разумного значения numeri c для преобразования. Точно так же в вашем фактическом коде: вы не можете преобразовать " " (одиночный пробел).

digits = [int(i) for i in digits]

Поскольку digits раньше было строкой, это повторяет каждый символ из строка. Если вы хотите перебрать каждое слово , вам нужно сначала разбить его на слова. Если вы просто хотите пропустить пробелы, вам также нужно сделать это явно.

Но первое, что вам нужно сделать, это подумать о проблеме . Как именно может выглядеть ваш ввод? Что именно вы хотите получить в результате в списке?

Вы хотите использовать int, а не float, потому что вы собираетесь выполнять целочисленную арифметику c при реализации алгоритм.

Когда вы получаете сообщение об ошибке, в котором говорится, что что-то не может быть преобразовано во что-то другое, вам нужно подумать о проблеме . Ошибка связана с тем, что вы пытаетесь преобразовать в ? Или это из-за того, что вы пытаетесь преобразовать из ? Чтобы понять это, первым делом нужно проверить, из чего вы пытаетесь преобразовать, и посмотреть, имеет ли это смысл для того, что вы делаете.

В вашем коде много других логических ошибок. Например, if digits[0] == 3 and digits[1] == 7 or 4 : не делает то, что вы хотите . На этом этапе вам будет лучше, если вы сначала следуете руководству, будьте более осторожны в целом и больше думая о проблеме , чем пытаясь получить помощь от Stack Overflow. Кроме того, пишите меньше кода за раз . Как только вы узнаете, каковы логические шаги для решения вашей проблемы, реализуйте каждый из них и сначала убедитесь, что он работает, , прежде чем продолжить. В вашем случае этот первый шаг - получение желаемого списка цифр.

0 голосов
/ 17 июня 2020

Я попробовал ваш код, и он запускается, если я ввожу номер карты без «-» или «» между группами di git. Вам также не нужно преобразовывать в числа с плавающей запятой.

Итак, я предполагаю, что вам нужно избавиться от символа '-' или '' во введенном номере карты. Если вы попросите пользователя вежливо использовать '-' только между группами, тогда:

digits = digits.replace('-', '')
digits = [int(i) for i in digits]

исправит эту проблему.

BTW - Как только я исправил эту проблему, он все равно не смог проверить мои номер карты как действительный, значит, там что-то не так.

0 голосов
/ 17 июня 2020

Идиоматическое c решение этой проблемы - попытаться преобразовать вещи в числа с плавающей запятой и реагировать только в случае неудачи. В этом случае это не удается, поэтому нам нужно добавить в список какой-то фильтр, чтобы игнорировать эти ошибки:

# helper method to check if an object can be casted to another type
# (e.g. calling the constructor you give it on the object you give it, and
# checking whether an error happens)
def is_castable(obj, T):
    try:
        T(obj)
        return True
    except ValueError:
        return False

# add a condition to the list comprehensions to ignore the item if it doesn't
# typecast properly
def card(digits):
    digits = [float(x) for x in digits if is_castable(x, float)]
    ...

Нет необходимости сначала приводить к int, если только вам не требуется что элементы округлены в меньшую сторону. Обычно float() принимает любую строку, которую примет int().

Кроме того, убедитесь, что обработка digits посимвольно - это то, что вы хотите делать. Если вы хотите токенизировать его (например, попросите пользователя ввести список, разделенный пробелами, например 2 5 8 13), вы можете рассмотреть возможность вызова .split() для исходного объекта digits.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...