简体   繁体   English

C 语言中 Luhn 算法的异常行为

[英]Unusual behavior with Luhn's algorithm in C

I've been doing a CS50 course and stumbled upon this "Credit" problem.我一直在做 CS50 课程,偶然发现了这个“信用”问题。 At the moment I'm testing it and due to insufficient cases provided in worksheet, I went to the recommended PayPal testing card numbers: https://developer.paypal.com/api/nvp-soap/payflow/integration-guide/test-transactions/#standard-test-cards Particularly:目前我正在测试它,由于工作表中提供的案例不足,我去了推荐的 PayPal 测试卡号: https ://developer.paypal.com/api/nvp-soap/payflow/integration-guide/test -transactions/#standard-test-cards特别是:

  • Mastercard 5555555555554444万事达卡5555555555554444
  • Mastercard 5105105105105100万事达卡5105105105105100
  • Mastercard 5199999999999991万事达卡5199999999999991
  • Mastercard 5299999999999990万事达卡5299999999999990

These refuse to cooperate.这些拒绝合作。 My program calculates the Luhn's value for them, and it's not close to being a multiplier of 10;我的程序为它们计算 Luhn 的值,它并不接近 10 的乘数; am I missing something, because other providers are working perfectly fine.我错过了什么吗,因为其他提供商工作得很好。

Results from code check:代码检查结果:

:( identifies 5555555555554444 as MASTERCARD
    expected "MASTERCARD\n", not "114\nINVALID\n..."
:( identifies 5105105105105100 as MASTERCARD
    expected "MASTERCARD\n", not "47\nINVALID\n"

My code:我的代码:

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

int get_sum_from_second_to_last(long temp_number);

int get_sum_from_odd_digits(long temp_number);

int length(long temp_number);

int return_first_n_digits(int n, long temp_number, int length);

int main()
{
    int final_sum = 0;
    long number = 0;
    do
    {
        number = get_long("Number: ");
    }
    while(number<0);
    final_sum = get_sum_from_second_to_last(number) + get_sum_from_odd_digits(number);
    printf("%i\n", final_sum);
    if(final_sum % 10 == 0)
    {
        if(length(number) == 15 && (return_first_n_digits(2, number, length(number)) == 34 || return_first_n_digits(2, number, length(number)) == 37))
        {
            printf("AMEX\n");
        }
        else
        {
            if((length(number) == 16 || length(number) == 13) && return_first_n_digits(1, number, length(number)) == 4)
            {
                printf("VISA\n");
            }
            else
            {
                if(length(number) == 16 && (return_first_n_digits(2, number, length(number)) == 51 || return_first_n_digits(2, number, length(number)) == 52 || return_first_n_digits(2, number, length(number)) == 53 || return_first_n_digits(2, number, length(number)) == 54 || return_first_n_digits(2, number, length(number)) == 55))
                {
                    printf("MASTERCARD\n");
                }
                else
                {
                    printf("This card provider recognition is not supported\n");
                }
            }
        }
    }
    else
    {
        printf("INVALID\n");
    }
}

int get_sum_from_second_to_last(long temp_number)
{
    int digit_current = 0;
    int counter = 1;
    int sum = 0;
    do
    {
        digit_current = temp_number % 10;
        if(counter%2 == 0)
        {
            if((digit_current*2)%10!=0)
            {
                sum = sum + (digit_current*2)%10 + (digit_current*2)/10;
            }
            else
            {
                sum = sum + digit_current*2;
            }
        }
        temp_number = temp_number/10;
        counter += 1;
    }
    while(temp_number);
    return sum;
}

int get_sum_from_odd_digits(long temp_number)
{
    int digit_current = 0;
    int counter = 1;
    int sum = 0;
    do
    {
        digit_current = temp_number % 10;
        if(counter%2 != 0)
        {
            sum = sum + digit_current;
        }
        temp_number = temp_number/10;
        counter += 1;
    }
    while(temp_number);
    return sum;
}

int length(long temp_number)
{
    int counter = 0;
    do
    {
        temp_number = temp_number/10;
        counter++;
    }
    while(temp_number);
    return counter;
}

int return_first_n_digits(int n, long temp_number, int length)
{
    int i;
    for(i = 0; i < length - n; i++)
    {
        temp_number = temp_number/10;
    }
    return temp_number;
}

The issue appears to be in your function for summing up the even numbered digits in the int get_sum_from_second_to_last function.问题似乎出在您的函数中,用于对int get_sum_from_second_to_last函数中的偶数位求和。 In that function, the digits are multiplied by a factor of two.在该函数中,数字乘以两倍。 Then according to information on how the Luhn's algorithm is supposed to work, if the result is a two-digit number, those digits are then supposed to be added together to derive a single digit.然后根据有关 Luhn 算法应该如何工作的信息,如果结果是两位数,则应该将这些数字相加以得出一位数。 It appears that doesn't always happen with the current testing within that function.似乎该功能中的当前测试并不总是发生这种情况。 Since the value of multiplying one digit by "2" can only result in two-digit numbers from "10" to "18", one can effectively derive the summation of the digits by just subtracting the value of "9" from the calculated result.由于一位数乘以“2”的值只能得到从“10”到“18”的两位数,因此只需从计算结果中减去“9”的值就可以有效地得出数字的总和.

With that, I offer up the following code snippet as an alternative summation of the even-numbered digits.有了这个,我提供了以下代码片段作为偶数数字的替代总和。

int get_sum_from_second_to_last(long temp_number)
{
    int digit_current = 0;
    int counter = 1;
    int sum = 0;
    do
    {
        digit_current = temp_number % 10;
        if(counter%2 == 0)
        {
            if((digit_current*2) > 9)
            {
                sum = sum + (digit_current * 2 - 9);
            }
            else
            {
                sum = sum + digit_current * 2;
            }
        }
        temp_number = temp_number/10;
        counter += 1;
    }
    while(temp_number);

    printf("Even digit sum: %d\n", sum);

    return sum;
}

FYI, you can leave out the printf() call.仅供参考,您可以省略printf()调用。 I added that just for some visual clarification.我补充说只是为了视觉上的澄清。

With that change, I tested out the four sample numbers in your narrative and they all produced a valid MASTERCARD result.通过这种更改,我测试了您叙述中的四个样本编号,它们都产生了有效的 MASTERCARD 结果。

Number: 5299999999999990
Even digit sum: 64
Current digit: 0
Current digit: 9
Current digit: 9
Current digit: 9
Current digit: 9
Current digit: 9
Current digit: 9
Current digit: 2
Odd digit sum: 56
Final sum: 120
MASTERCARD

As a further test, I actually tested out a number for AMEX and for VISA and those worked as well.作为进一步的测试,我实际上为 AMEX 和 VISA 测试了一个号码,这些号码也很有效。

I hope that clarifies things.我希望这能澄清事情。

Regards.问候。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM