Моя попытка алгоритма Луна (для действия кредитной карты), похоже, распознает некоторые карты, но не другие

#c #cs50 #luhn

#c #cs50 #луна

Вопрос:

Я создал некоторый код для имитации алгоритма Луна для проверки действительности кредитных карт. Он успешно распознает карты American Express (15-значные номера, начинающиеся с 34 или 37 ), но когда я пытаюсь использовать Mastercard (16 цифр, начинающихся с 51 , 52 , 53 , 54 , или 55 ), он их не распознает. Карты Visa имеют 13 или 16 цифр и начинаются с цифры 4 , мой код, похоже, правильно идентифицирует 16-значные регистры, но не 13-значные. Я просмотрел свой код и дважды проверил свои числовые диапазоны, и, похоже, я не могу точно определить, почему некоторые карты проходят, а другие нет. Любая помощь будет с благодарностью.

Редактировать:

Я почти исправил проблему, я изменил ее, и теперь все номера карт проверяются, но теперь он распознает недопустимый номер ( 4111111111111113 ) как Visa. Вот мой обновленный код:

 #include <math.h>
#include <cs50.h>
#include <stdio.h>

long long number;

int main(void)
{
    long long i = 0;
    long long b;
    long long m = 10;
    long long n = 1;

    number = get_long_long("Number?n");

    do
    {
        long long a = number % m;
        b = number - a;
        long long c = b % (m * 10);
        long long d = c / m;
        long long e = d * 2;
        if (e < 9)
        {
            i = i   e;
        }
        else
        {
            i = i   (e - 10   1);
        }
        
        {
            m = m * 100;
        }
    }
    while (b > 0);

    do
    {
        long long a = number % n;
        b = number - a;
        long long c = b % (n * 10);
        long long d = c / n;
        long long e = d;
        if (e < 9)
        {
            i = i   e;
        }
        else
        {
            i = i   (e - 10   1);
        }
        
        {
            n = n * 100;
        }
    }
    while (b > 0);

    int f = i % 10;
    if (((f == 0) amp;amp; (number > 339999999999999) amp;amp; (number < 350000000000000)) || ((number > 369999999999999) amp;amp; (number < 380000000000000)))
    {
        printf("AMEXn");
    }
    else
    if ((f == 0) amp;amp; (number > 5099999999999999) amp;amp; (number < 5600000000000000))
    {
        printf("MASTERCARDn");
    }
    else
    if (((f == 0) amp;amp; ((number > 3999999999999) amp;amp; (number < 5000000000000))) || ((number > 3999999999999999) amp;amp; (number < 5000000000000000)))
    {
        printf("VISAn");
    }
    else
    {
        printf("INVALIDn");
    }
}
 

Комментарии:

1. Возможно, я что-то здесь упускаю, но где / как это только удваивает каждую вторую цифру?

2. @EdmCoff Я использую m и n в качестве входных данных для операторов модуля, которые увеличиваются на * 100 на каждой итерации. Имеет ли это смысл?

3. Спасибо. Я пропустил это. Почему оба цикла удваивают цифру? (Я предполагаю, что ваш второй цикл не должен удваивать цифры). Кроме того, вы уверены, что можно начинать отсчет вторых цифр с конца номера? (например, для четного числа цифр, например, 123456, я предполагаю, что вы хотите удвоить 2/4/6, а не 5/3/1)

4. @EdmCoff Ваше наблюдение было точным — я не знаю, почему я удвоил цифру дважды. Я изменил это, и теперь он распознает все карты — однако он по-прежнему распознает недопустимую последовательность (411111111111111113) как Visa.

5. Я вижу, что вы исправили проблему с удвоением, но я не вижу изменений для учета начала с конца числа.

Ответ №1:

Я вижу, что у вас возникли проблемы при попытке проверить длину некоторых карт. Чтобы исправить это, используйте функцию, которая автоматически проверяет длину long . Вы можете использовать некоторую логику с функцией для правильного определения длины визы.

Вот функция для проверки длины длинной переменной.

 int get_long_len(long value)
{
    int l = 1;
    while (value > 9)
    {
        l  ;
        value /= 10;
    }
    return l;
}
 

Он принимает значение long и возвращает длину.

Комментарии:

1. Сначала я был смущен тем, что вы имели в виду под «длиной длинной». Из чтения, я думаю, вы имеете в виду «количество десятичных цифр, если значение было напечатано с основанием 10». Это верно?

2. @jwd Нет в C есть переменный тип с именем long, который в основном представляет собой число, которое может содержать больше цифр. Целое число может доходить только до, я думаю, где-то около 2-3 миллионов, в то время как длинная переменная может позволить вам назначать гораздо большие числа. По сути, я говорю о «длине числовой переменной с именем long», поскольку номера кредитных карт очень длинные, было бы лучше присвоить ему значение long, потому что иногда int может его не принять.

3. Я понимаю, что тип long , который обычно равен 64 битам, а не 32 int . Но это двоичные числа. Их «длина» — это количество битов (по крайней мере, на мой взгляд). Но я думаю, что здесь вы говорите о «длине», как если бы они были напечатаны как «12345 …»?

4. Да, я говорю о длине, так как при подсчете цифр, например, длина 096, будет равна 3. Не двоичные цифры, а просто подсчет того, что вы видите с помощью C в вашей IDE.