2

我一直在尝试创建一个程序,可以根据Hans Peter Luhn 的算法检查信用卡号是否有效。但是,我只能让它适用于某些输入。

// 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 测试信用卡号页面,所以我知道它们是有效的。

那么我做错了什么?


通过程序澄清细节,如果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;
}
4

2 回答 2

3

您会想要更改i % 2i % 2 == intlen (num) % 2或类似的;你应该每第二个数字加倍,但从右边开始;即不包括最后的校验位:

从最右边的数字(即校验位)开始,向左移动,每第二位的值加倍;…</p>

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

于 2014-06-24T04:12:23.870 回答
0

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

无论如何,我们需要从右边抓取数字。我们甚至不需要计算数字;只需继续拉出最右边的数字,直到数字变为 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);
        }
    }
}
于 2014-06-24T04:51:02.640 回答