checksum validation

I am having issues to figure it out how can i do checksum for very large number such as having more than 45 digit long? i used assign long long but it can solve only upto 18 digit. here is my code below.


#include <iostream>
#include <cmath>
#include <limits>

using namespace std;
int getLength(unsigned long long);
int getSum(unsigned long long);

int main()
{
unsigned long long ccnum;
int digits;

cout << "\n\tEnter your ID number: ";
cin >> ccnum;
cin.ignore();

int sum = getSum(ccnum);
cout << "\tsum = " << sum << "\n";
// validation the number valid or not
int lastdigit = ccnum % 10;
if (sum % 10 == 0) {
cout << "\nID number is valid! Thank you.\n"
<< "\n************************************************\n";
}

else if (sum % 10 != 0) {
cout << "\nSum not divised by 10. ID is invalid! Sorry." << endl;
lastdigit > (sum% 10) ? lastdigit = lastdigit - sum % 10 : lastdigit += sum % 10; // advide number should have
cout << "Your last number should be: " << lastdigit << endl
<< "\n************************************************\n";

}
//system("pause");
cout << "\tpress enter continue..";
cin.get();
return 0;
}
int getLength(unsigned long long num) {
return ceil(log10((unsigned long long)num + 1));
}

bool isEven(unsigned long long userNum) {
if ((userNum % 2) == 1)
return false;
else
return true;
}

int getSum(unsigned long long userNum) {
int count = 0;

int digit = 0;
int sum = 0;
unsigned long long runningNum = userNum;

for (int i = 0; i < (getLength(userNum)); i++) {
digit = runningNum % 10;
runningNum = runningNum / 10;

if (isEven(count)) {
sum += digit;
}
else {
digit = digit * 2;
if (digit > 9) {
int onesPlace = digit - 10;
digit = onesPlace + 1;
}
sum += digit;
}

count++;
}
return sum;
}

bool isDivisible(int userNum) {
return false;
}
The number is not a "number"; it is just an array of digits.

A string is an array of chars. You can look at each char separately. You can convert a char into a digit.
yeah rewrite the entire thing using string input.

Consult an ASCII table for converting the char within the string array into a number. If the resulting number is greater than 9 or less than 0, then its an invalid character (not a number)

The program runs tho, and the suggested last number output is definitely related to the input, although it's often suggesting the last number be a 10 or a 12. Try some very short inputs to see an example of this:
11 gives 4
22 gives 8
1 gives 2
2 gives 4
3 gives 6
111 gives 5
1111 gives 7
11111 gives 8
and
111111 gives 10
33 gives 12

but look:
$ ./biwash.exe

Enter your ID number: 34
sum = 10

ID number is valid! Thank you.

...so it's definitely doing something and if you rewrite it with strings I know you'll get it doing what you want no matter how long the input.
Here's a start... It does NOT produce the same results as the original, for a variety of reasons, some of which are in the comments. But it works thru the string and does something like what your code did. You should be able to fix it. It compiles without warnings and the input "43" passes the test (instead of "34").

I could fix it if I knew what the original objective was exactly, but I'm still not sure why every other number is being multiplied or something (that's not what usually happens in a checksum?)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <iostream>
#include <cmath>
#include <limits>

int getSums(std::string);

int main()
   {
   unsigned long long ccnum;
   std::string digits;
   int sum=0; //declare up front

   std::cout << "\n\tEnter your ID number: ";
   getline(std::cin, digits);

   sum = getSums(digits);
   std::cout << "\tsum = " << sum << "\n";
   // validation the number valid or not
   int lastdigit = ccnum % 10;
   if (sum % 10 == 0) {
      std::cout << "\nID number is valid! Thank you.\n"
      << "\n************************************************\n";
      }

   else if (sum % 10 != 0) {
      std::cout << "\nSum not divised by 10. ID is invalid! Sorry." << std::endl;
      lastdigit > (sum% 10) ? lastdigit = lastdigit - sum % 10 : lastdigit += sum % 10; // advide number should have
      std::cout << "Your last number should be: " << lastdigit << std::endl
      << "\n************************************************\n";
      }

   std::cout << "\tpress enter continue..";
   std::cin.get();\
//A DEBUGGING LINE I USED
//   std::cout << "\tinput digits was " << digits << "\n";
   return 0;
   }

bool isEven(unsigned long long userNum) {
//this is called with the count, which is an integer. Not sure what was meant to be done here. Just leaving it as is.

   if ((userNum % 2) == 1)
   return false;
   else
   return true;
   }

int getSums(std::string digits) {
   int count = 0;
   int digit = 0;
   int sum = 0;
   int onesPlace = 0 ; //declare up front

   std::cout << "entering loop...\n" ;
   while (digits[count] != 0) {   //risk of buffer overrun on malformatted string?
      digit = digits[count]-48; //direct conversion assumes ASCII character space
      if (digit>9 || digit <0) {
         digit=0; // non-numbers are treated as being zeroes. you could set an error flag instead here.
         }
      if (isEven(count)) {
//note:the original counted the digits backwards, so for even-length strings, the results are different...
         sum += digit;
         }
      else {
         digit = digit * 2;
         if (digit > 9) {
            onesPlace = digit - 10;
            digit = onesPlace + 1;
            }
         sum += digit;
         }
//A DEBUGGING LINE
//      std::cout << "." << digits[count] << "." ;
      count++;
      }
   return sum;
   }
Hi biwash

Consider using this if you are allowed:

http://www.boost.org/doc/libs/1_66_0/libs/multiprecision/doc/html/index.html
A 45 digit number is going to require 45*(log(10)/log(2) bits of precision. 150 bits of precision. If you're using a float, the exponent part will require even more bits than that.

I'm pretty sure the digit requirement of the assignment was chosen in order to force the student to not use numbers at all, but rather to approach the assignment from the standpoint of an array.

What I'm not sure about is how the assignment wanted the checksum computed in the first place, or if the existing code is even correct when solving 18 digit input (was input samples provided to verify it, etc.). Since I switched the order of computation, the results are different. That's fine with me, my primary purpose in replying wasn't to complete the assignment for the student, but just to show how to approach the problem from a non-integer standpoint. The student can resolve issues like the place value of each number, etc if they choose to work with the code I posted...
Consult an ASCII table for converting the char within the string array into a number
Actually you don't even need the table, you just have to know that the digit characters are represented by consecutive values from 0 to 9. Thus you can just subtract '0' to get the numeric value:
1
2
char ch = '6';
int asciiVal = '6' - '0';

ooh that's a lot more elegant, and makes the code more portable too. thanks!
Topic archived. No new replies allowed.