【问题标题】:Validating card credit numbers验证信用卡信用卡号
【发布时间】:2014-08-14 05:03:41
【问题描述】:

我一直在尝试创建一个程序,该程序可以根据Hans Peter Luhn's algorithm 检查信用卡号是否有效。但是,我只能让它对某些输入起作用。

// Loop through every digit in the card number
for ( int i = 0; i < intlen (num); ++i )
{
    nextDigit = getDigit (num, i);

    // If every other number...
    if ( i % 2 )
    {
        nextDigit *= 2;

        // ...times by two and add the individual digits to the total
        for ( int j = 0; j < intlen (nextDigit); ++j )
        {
            total += getDigit (nextDigit, j);
        }
    }
    else
    {
        total += nextDigit;
    }
}

当我使用AMEX 卡号378282246310005 时,它可以正常工作并告诉用户它是有效的。但是,一旦我尝试VISA 卡号4012888888881881 它说它是无效的。我尝试进行完整性检查并手动进行以查看我的程序是否错误,但我推断出相同的结果。这些卡号取自 Paypal 测试信用卡号 page,所以我知道它们是有效的。

那我做错了什么?


通过程序澄清细节,如果total modulo 10 == 0那么卡号是有效的。

调用的函数:

// Function to return length (number of digits) of an int

int intlen (long long n)
{
    int len = 1;

    // While there is more than 1 digit...
    while ( abs (n) > 9 )
    {
       // ...discard leading digits and add 1 to len
       n /= 10;
       ++len;
    }

    return len;
}

// Function to return a digit in an integer at a specified index

short getDigit (long long num, int index)
{
    // Calculating position of digit in integer
    int pos = intlen (num) - index;

    // Discard numbers after selected digit
    while ( pos > 1 )
    {
        num /= 10;
        --pos;
    }

    // Return right-most digit i.e. selected digit
    return num % 10;
}

【问题讨论】:

  • 您可能必须提供其余代码才能确定;尤其是getDigitintlen
  • 我希望那些信用卡号码不是来自真正的活跃卡...... ;)
  • @selbie:这些是测试号码。

标签: c luhn


【解决方案1】:

您需要将i % 2 更改为i % 2 == intlen (num) % 2 或类似名称;你应该每隔一个数字加倍,但是starting from the right;即不包括最后的校验位:

从最右边的数字,即校验位,向左移动,每第二位的值加倍; …

您尝试验证的AMEX号码的原因是因为它是奇数位数;无论您是从前面跳过还是从后面跳过,相同的数字都会翻倍。

【讨论】:

    【解决方案2】:

    当我查看这个以查找错误时,我重新编写了程序以使其更简单一些。作为副作用,这会更快。

    无论如何,我们都需要从右边抓取数字。我们甚至不需要计算数字;一直拉掉最右边的数字,直到数字变为 0。如果数字开始为 0,则校验和通常为 0,并且代码仍然正确。

    我从测试页中获取了所有数字。这似乎是正确的,除了一个数字:76009244561(在测试页面中列为“Dankort (PBS)”)。我用 Wikipedia 页面上的 Python 代码尝试了这个数字,但这个数字又被拒绝了。我不知道为什么这个数字与其他数字不同。

    #include <stdbool.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    bool check_one(long long num)
    {
        int checksum = 0;
        int i = 1;
    
        for (int i = 1; num; num /= 10, ++i)
        {
            int d = num % 10;
    
            if (i % 2 == 0)
            {
                // even digit: double and add digits of doubled value
                d *= 2;
                if (d < 10)
                {
                    // only one digit: we doubled a 0-4 so number is 0-8
                    checksum += d;
                }
                else
                {
                    // two digits: we doubled a 5-9 so number is 10-18
                    checksum += (d % 10);
                    checksum += (d / 10);
                }
            }
            else
            {
                // odd digit: just add
                checksum += d;
            }
        }
        return (checksum % 10) == 0;
    }
    
    static long long const valid_nums[] = 
    {
        378282246310005,
        371449635398431,
        378734493671000,
        5610591081018250,
        30569309025904,
        38520000023237,
        6011111111111117,
        6011000990139424,
        3530111333300000,
        3566002020360505,
        5555555555554444,
        5105105105105100,
        4111111111111111,
        4012888888881881,
        4222222222222,
        76009244561,
        5019717010103742,
        6331101999990016,
    };
    
    static size_t len_valid_nums = sizeof(valid_nums) / sizeof(valid_nums[0]);
    
    static long long const non_valid_nums[] = 
    {
        378282246310006, // add 1 to valid
        371449635398432,
        378734493671001,
        5610591081018205, // swap last two digits
        30569309025940,
        38520000023273,
        601111111111111, // delete last digit
        601100099013942,
        353011133330000,
    };
    
    static size_t len_non_valid_nums =
            (sizeof(non_valid_nums) / sizeof(non_valid_nums[0]));
    
    
    main()
    {
        bool f;
    
        for (int i = 0; i < len_valid_nums; ++i)
        {
            long long num = valid_nums[i];
            f = check_one(num);
            if (!f)
            {
                printf("Number %lld considered invalid but should be valid\n", num);
            }
        }
    
        for (int i = 0; i < len_non_valid_nums; ++i)
        {
            long long num = non_valid_nums[i];
            f = check_one(num);
            if (f)
            {
                printf("Number %lld considered valid but should be invalid\n", num);
            }
        }
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-01
    • 2011-05-09
    • 2021-08-16
    • 2011-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多