Luhn algorithm validation and Luhn algorithm validation
Luhn test and verification
The Luhn formula is a widely used system used to verify the identification number. It doubles the value of every number based on the original ID number. Add the values of individual numbers together (if the value after doubling is 2 digits, add the two numbers respectively ). If 10 can be divisible after the addition, the ID number is valid.
Write a program, accept an ID number of any length, and determine whether the ID number is legal according to the Luhn formula. This program must process the character previously read before reading the next character.
The process is somewhat complicated. upload an image here for your understanding:
Remember: The test of the final ID number should be able to be divided by 10, or should end with 0.
Next, let's break down the problem together.
(Note: we do not need to deal with these problems in specific order .)
First, we will deal with the number that is greater than or equal to 10 after doubling:
If we use a separate number 0 ~ Start 9 and double them. The maximum value is 18. Therefore, there are only two possibilities: If the value after doubling is a single number, no further processing is required; if the value after doubling is greater than or equal to 10, it must be in the range of 10 ~ So the first number is always 1. Let's verify it with a code:
1 int digit; 2 printf ("Enter a single digit number, 0-9:"); 3 scanf ("% d", & digit ); 4 int doubledDigit = digit * 2; // The program reads a number and doubles its value by 5 int sum; 6 if (doubledDigit> = 10) 7 sum = 1 + doubledDigit % 10; // sum calculation 8 else 9 Sum = doubledDigit; 10 printf ("sum of digits in doubled number: % d \ n", sum ); // output the sum result
The verification result is as follows:
We can convert this code into a short function to simplify future code. (Is it far-sighted ?)
1 int doubleDigitValue (int digit) 2 {3 int doubledDigit = digit * 2; // The program reads a number and doubles its value by 4 int sum; 5 if (doubledDigit> = 10) 6 sum = 1 + doubledDigit % 10; // sum calculation 7 else 8 sum = doubledDigit; 9 return sum; 10}
Now, we read the separate number of the ID number:
If we read the ID number in the form of a numeric value (such as int), a long number will be read and many things need to be done. In addition, the maximum integer that can be read is limited. However, in this case, the ID number can be of any length. Therefore, we must read data by character. This means that we need to know how to read a character that represents a number and convert it to the integer type to perform mathematical operations on it. See the following code:
1 char digit;2 printf("Enter a one-digit number:");3 scanf("%c",&digit);4 int sum = digit;5 printf("Is the sum of digits:%d?\n",sum);
The running result is:
Character 7 is stored in 55 characters. Therefore, when we use this character as an integer, the result is 55.
Therefore, we need a mechanism to convert character 7 to integer 7.
We can create a table that contains the original value and the target value, as well as the error between the two values.
Escape code-target integer
Character |
Verification Code |
Target integer |
Difference |
0 |
48 |
0 |
48 |
1 |
49 |
1 |
48 |
2 |
50 |
2 |
48 |
3 |
51 |
3 |
48 |
4 |
52 |
4 |
48 |
5 |
53 |
5 |
48 |
6 |
54 |
6 |
48 |
7 |
55 |
7 |
48 |
8 |
56 |
8 |
48 |
9 |
57 |
9 |
48 |
The difference between the attention code and the target integer is always 48, so what we need to do is to subtract the attention code from this value. The 48 is exactly the 0 verification code, so we can adopt a more general and easier-to-understand solution: subtract the 0 verification code rather than the predefined value like 48:
1 char digit;2 printf("Enter a one-digit number:");3 scanf("%c",&digit);4 int sum = digit - '0';5 printf("Is the sum of digits:%d?\n",sum);
The running result is:
Now, let's go to the next part of the problem and determine which numbers need to be doubled:
We can first try to limit the length to 6, then we only need to read 6 numbers, sum them, and then determine whether their sum is divisible by 10. The Code is as follows:
1 char digit; 2 int checksum = 0; 3 printf("Enter a six-digit number:"); 4 for(int position = 1;position <= 6;position++){ 5 scanf("%c",&digit); 6 checksum += digit - '0'; 7 } 8 printf("Checksum is:%d\n",checksum); 9 if(checksum%10 == 0)10 printf("Valid:Checknum is divisible by 10\n"); 11 else12 printf("Invalid:Checknum is not divisible by 10\n");
The running result is:
Now, we need to increase the logic for the actual Luhn test formula to double the number with an odd number starting from the left. We can use the touch operator (%) to determine the positions of the odd and even numbers, because the even number is defined to be divisible by 2. Therefore, if the result of expression position % 2 is 1 and this position is an odd number, it should be doubled. By the way, after doubling, if the result is greater than or equal to 10, you also need to sum the numbers of the results. The Code is as follows (just change the for loop ):
1 for(int position = 1;position <= 6;position++){2 scanf("%c",&digit);3 if(position%2 == 0) checksum += digit - '0';4 else checksum += doubleDigitValue(digit - '0');5 }
The running result is:
So far, we have made great progress on this issue, but we still need to complete some steps to write code for ID numbers of any length. To solve this problem, we need to adopt the division and Control Law.
First, consider how to deal with identification numbers with an even number.
The first problem we are facing is how to determine that we have reached the end of the ID number. If you Enter a multi-digit ID and press Enter to end the process, and we read the input characters one by one, so what are the characters read after the last number? Let's try it out with code:
1 printf("Enter a number:");2 char digit;3 while(1){4 scanf("%c",&digit);5 printf("%d\n",int(digit));6 }
The running result is:
Enter 1234 and the result is 49 50 51 52 10 (the result is based on the ASCII code ). From the running results, we can see that 10 is the result we are looking for, so we can replace the for loop with a while loop in the previous Code:
1 // process any even-length identifier 2 char digit; 3 int checksum = 0; 4 int position = 1; 5 printf ("Enter a number with an even number of digits: "); 6 scanf (" % c ", & digit); // read the first value 7 while (digit! = 10) {// used to check whether the value of the escape code is the row end character 8 if (position % 2 = 0) // judge 9 checksum + = digit-'0' for even digits; 10 else checksum + = 2 * (digit-'0'); 11 scanf ("% c ", & digit); // read each subsequent value 12 position ++; 13} 14 printf ("Checksum is: % d \ n", checksum ); 15 if (checksum % 10 = 0) 16 printf ("Valid: Checksum is divisible by 10 \ n"); 17 else18 printf ("Invalid: checksum is not divisible by 10 \ n ");
The running result is:
Now we have solved the problem of "how to determine that we have reached the end of the ID number.
To exhaust every possibility, the length of the identification number must be an odd or even number. If we know the length in advance, we can know that we should double the number of odd digits or even digits. However, we do not know this information before reading this identification number. Before thinking about this problem, let's first look at another problem:
Write a program to read 10 integers from the user. After All integers are entered, the number of positive or negative numbers in these numbers must be displayed.
Writing idea: You need a variable that counts positive numbers and another variable that counts negative numbers. When you specify a specific request at the end of the program, you only need to display the appropriate variable as the response. The Code is as follows:
1 int number; 2 int positiveCount = 0; 3 int negativeCount = 0; 4 for (int I = 1; I <= 10; I ++) {5 scanf ("% d", & number); 6 if (number> 0) positiveCount ++; // The Count value is 7 if (number <0) negativeCount ++; // count negative values 8} 9 char response; // select to answer 10 printf ("Do you want the (p) ositive or (n) egative count? "); 11 getchar (); // swallow the carriage return 12 scanf (" % c ", & response); 13 if (response = 'P ') 14 printf ("Positive Count is % d \ n", positiveCount); 15 if (response = 'n') 16 printf ("Negative Count is % d \ n ", negativeCount );
The running result is:
This analogy shows the method we need to solve the Luhn test and problem: we track the current test in two ways at the same time, the identifier is an odd length and an even length. When we read this number and determine its true length, we select the variables that indicate the correct check.
Now, we can combine all the code to solve this problem.
Start AC !!!
1 char digit; 2 int oddLengthChecksum = 0; 3 int evenLengthChecksum = 0; 4 int position = 1; 5 printf("Enter a number:"); 6 scanf("%c",&digit); 7 while(digit != 10){ 8 if(position%2 == 0){ 9 oddLengthChecksum += doubleDigitValue(digit - '0');10 evenLengthChecksum += digit - '0';11 }12 else{13 oddLengthChecksum += digit - '0';14 evenLengthChecksum += doubleDigitValue(digit - '0');15 }16 scanf("%c",&digit);17 position++;18 }19 int checksum;20 if((position - 1)%2 == 0) checksum = evenLengthChecksum;21 else checksum = oddLengthChecksum;22 printf("Checksum is:%d\n",checksum);23 if(checksum%10 == 0)24 printf("Valid:Checknum is divisible by 10\n"); 25 else26 printf("Invalid:Checknum is not divisible by 10\n");
The running result is:
Conclusion: After writing this blog post for one night, my eyesight began to blur, and there were some headaches. It may be that I went out and went out to play yesterday afternoon. But today we are very happy to watch a complete algorithm into a small piece of detailed analysis and code test, immersed in it, a little closer to the truth, i'm excited and happy! At the beginning, I still had some questions about function calls and carriage return in the program. However, with the help of a friend, I still succeeded. Most importantly, I have a deeper understanding of this algorithm.
I have to admit that I began to like writing, so the question is, will I like writing as scheduled?