How can I improve or shorten my implementation of the Luhn algorithm?
int digits;
cout << "enter the numer of digits" << endl;
cin >> digits;
int Acc_num[digits];
int shuma = 0;
The shuma
variable is the sum.
I created an array to store the digits from the string credit_card
.
And asked the user how many digits his credit card has, etc. (the digits
int).
string credit_card;
cout << "enter the identification number" << endl;
cin >> credit_card;
// store the digits
for (int i = 0 ; i < digits ; i ++ ) {
Acc_num[i] = credit_card[i];
}
for (int i = 0 ; i <= (digits - 1) ; i ++ ) {
Acc_num[i] -= 48;
}
// Double every other
for (int i = 1 ; i <=digits ; i ++) {
if (i % 2 == 0) {
Acc_num[i-1] = 2 * Acc_num[i-1];
} else {
Acc_num[i-1] = Acc_num [i-1];
}
}
//Sum digits
for (int i = 1 ; i <= digits ; i ++ ) {
if (Acc_num[i-1] > 9 && i % 2 == 0) {
int mod = Acc_num[i-1] % 10 ;
Acc_num[i-1] = 1 + mod ;
} else {
Acc_num[i-1] = Acc_num[i-1];
}
}
// the sum
for (int i = 0 ; i <= (digits - 1) ; i ++ ) {
shuma += Acc_num[i];
}
if (shuma % 10 == 0) {
cout << "\nthis number is valid" << endl;
} else {
cout << "\nthis number is invalid" << endl;
}
2 Answers 2
Doubling the even digits and subtracting 9 if> 10 would be mod 9 so a really simple, compact algorithm might be:
for (int i = 0; i < nDigits; i++)
{
int digit = digitArray [i] - '0'; // Char to number
if (i & 1) // Digit 1, 3, 5 not 0, 2, 4 - "even digits" starting at 1
if ((digit <<= 1) >= 10) // Double it, check >= 10
digit -= 9; // Same as summing the digits
shuma += digit;
}
int checksum = shuma % 10;
-
\$\begingroup\$ Code error - should have been >= 10, not > 10 but you get the idea. Break the problem down, solve with math where possible and don't write code that "does" things, write code that "takes care of" them. \$\endgroup\$Mike– Mike2016年04月24日 20:27:25 +00:00Commented Apr 24, 2016 at 20:27
-
\$\begingroup\$ One correctness consideration is that if the number is excessively long,
shuma
can overflow, which will probably ruin the checksum value. To avoid that possibility, you can changeshuma += digit;
toif ((shuma += digit) >= 10) shuma -= 10;
and eliminate theint checksum = shuma % 10;
line, sinceshuma
will already be a modulo 10 reduced residue. \$\endgroup\$Chai T. Rex– Chai T. Rex2018年06月29日 23:03:27 +00:00Commented Jun 29, 2018 at 23:03
It looks like you could do all of those calculations in one loop. Also, all of the places where you do Acc_num[i-1] = Acc_num [i-1];
amount to a no-op, so you could remove them.