I've been doing a CS50 course and stumbled upon this "Credit" problem. 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:
5555555555554444
5105105105105100
5199999999999991
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; 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. 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. 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.
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. 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.
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.
I hope that clarifies things.
Regards.