How do you implement your own string to integer conversion - c++

So I want to take a string in such as 8302 and convert this into an integer by creating my own function and not using the stoi/atoi functions.
I tried so far by doing:
int stringToInt(string input)
{
int i = 0;
while(input[i] >= '0' && input[i] <= '9')
{
input[i] = input[i] * 10 + ......
i++;
}
return i;
}
I know i need to keep multiplying by 10 everytime i find an integer so i can increase it e.g 123 = 1*10*10+2*10+3. but i dont know how to code this. could anyone suggest a method?

It might be easiest to do it in a recursive manner. Use the following idea:
8302 = 830 * 10 + 2
That is:
If there is only one char in the string - return it; otherwise continue
Separate the last char in the string
Convert the string (without the last char) to integer - using recursion
Multiply by 10 and add the last char
There are a lot of details here:
how to convert 1 char to an integer? - subtract '0' from it
how to separate a char from the rest of the string? - use substr
when you have a working recursive solution, you might want to convert it to an iterative solution - this will make it faster, but maybe less readable
what to do with invalid strings like "aaa" or "123haha" - my algorithm doesn't handle that

Before you could define a char2int conversion:
inline int ctoi(char c) {
switch (c) {
case '0':
return 0;
case '1':
return 1;
case '2':
return 2;
case '3':
return 3;
case '4':
return 4;
case '5':
return 5;
case '6':
return 6;
case '7':
return 7;
case '8':
return 8;
case '9':
return 9;
default:
throw std::runtime_error("Invalid char conversion");
}
}
And use it:
int my_stoi_dec(const std::string& str) {
int rtn = 0;
int exp = 1;
for (auto cp = str.crbegin(); cp != str.crend(); ++cp) {
char c = *cp;
if (isdigit(c)) {
rtn += ctoi(c) * exp;
exp *= 10;
} else if (c == '+') {
return rtn;
} else if (c == '-') {
return rtn * -1;
} else {
throw std::runtime_error("Integer error conversion");
}
}
}

This one is very close to your attempt:
int toInt(const std::string& input)
{
int i = 0;
for (const auto c : input)
{
if (c < '0' || c > '9')
break;
i = i*10 + c-'0';
}
return i;
}
The only assumption is that the characters '0' to '9' lie directly next to each other in the character set. The if statement makes sure that we stop at non-digit characters. The digit-characters are converted to their integer value using c-'0'.
Please keep in mind that this only parses the first digits of a string. Strings that start with a sign + or - are not considered.

A good way is to find your first digit and go from there make a multiplayer variable and multiply it by ten every digit. for every char you add you have to subtract '0' from it as '0' is not equal to int 0.
example:
string s = "12346";
int multiplayer = 1;
int i = 0;
int result = 0;
while (s[i] >= '0' && s[i] <= '9')
++i;
--i;
for(i ; i >= 0 ; --i){
result += (s[i] - '0') * multiplayer;
multiplayer *= 10;
}

It is much better that you start your conversion from right to left.
So you will iterate your string starting from its end, and ending on its beginning. On each iteration, we will take the character, convert it to int and multiply it with its multiplier (its position in the result integer) and then add it to the final result.
This should work:
#include <iostream>
#include <string>
int stringToInt(std::string input)
{
int result = 0;
int multiplier = 1;
for (int i = input.length() - 1; i >= 0; i--) // start from right
{
if (input[i] - '0' < 0 || input[i] - '0' > 9) // if any character is not an integer, return maximum negative
{
result = INT16_MIN;
break;
}
result += (input[i] - '0') * multiplier; // convert to int, get its position and then add it to result.
multiplier *= 10; // get next position
}
return result;
}
int main()
{
std::string MyEx = "123456";
int MyInt = stringToInt(MyEx);
std::cout << MyInt;
return 0;
}

void enforce( bool b ) {
if ( !b ) {
throw std::range_error("Not a valid string to convert to integer");
}
}
int stringToInt(std::string) {
for ( std::size_t i( 0 ); i != ( last - first ); ++i ) {
enforce( ( '0' <= first[ i ] ) && ( first[ i ] <= '9' ) );
result += pow(10,i) * ( first[ i ] - '0' );
}
}
Source

Related

run-length encoding is not working with big numbers

I have a assingment were I need to code and decode txt files, for example: hello how are you? has to be coded as hel2o how are you? and aaaaaaaaaajkle as a10jkle.
while ( ! invoer.eof ( ) ) {
if (kar >= '0' && kar <= '9') {
counter = kar-48;
while (counter > 1){
uitvoer.put(vorigeKar);
counter--;
}
}else if (kar == '/'){
kar = invoer.get();
uitvoer.put(kar);
}else{
uitvoer.put(kar);
}
vorigeKar = kar;
kar = invoer.get ( );
}
but the problem I have is if need to decode a12bhr, the answer is aaaaaaaaaaaabhr but I can't seem to get the 12 as number without problems, I also can't use any strings.
try to put a repeated character when next is not numeric or end of string.
For prepare this, it needs to make number by parsing string.
about this, I recommend you to find how to convert string to integer in real time at C++.
bool isNumeric(char ch) {
return '0' <= ch && ch <= '9';
}
string decode(const string& s) {
int counter = 0;
string result;
char prevCh;
for (int i = 0; i < s.length(); i++) {
if (isNumeric(s[i])) { // update counter
counter = counter * 10 + (s[i] - '0');
if (isNumeric(s[i + 1]) == false || i + 1 == s.length()) {
// now, put previous character stacked
while (counter-- > 1) {
result.push_back(prevCh);
}
counter = 0;
}
}
else {
result.push_back(s[i]);
prevCh = s[i];
}
}
return result;
}
now, decode("a12bhr3") returns aaaaaaaaaaaabhrrr. it works well.

Convert string to float or integer without using built in functions (like atoi or atof)

I'm new to C++ and our teacher asked us to get a function that does the above title. So far I've got a function that converts a string to an integer, but I have no idea about how to modify it to make it work if the numbers in the string would represent a float.
int convert(char str[], int size) {
int number = 0;
for (int i = 0; i < size; ++i) {
number += (str[i] - 48)*pow(10, (size - i - 1));
}
return number;
}
If I run:
char myString[] = "12345";
convert(myString, 5);
I get:
12345
But if I run:
char myString[] = "123.45";
convert(myString, 5);
I get:
122845
How could I modify my program to work with floats too? I know convert function is meant to return an int so, should I use two more functions?
I was thinking about one that determinates if the string is inteded to be converted to an integer or a string, and the other that'll actually convert the string to a float.
Here is the function for doing so...
template<class T, class S>
T convert_string_to_number(S s)
{
auto result = T(0.l);
if (s.back() == L'F' || s.back() == L'f')
s = s.substr(0u, s.size() - 1u);
auto temp = s;
auto should_add = false;
if (!std::is_floating_point<T>::value)
{
should_add = temp.at(temp.find_first_of(L'.') + 1) >= '5';
temp.erase(temp.begin() + temp.find_first_of(L'.'), temp.end());
}
else if (temp.find_first_of(L'.') != S::npos)
temp.erase(temp.begin() + temp.find_first_of(L'.'));
for (int i = temp.size() - 1u; i >= 0; --i)
if (temp[i] >= L'0' && temp[i] <= L'9')
result += T(std::powl(10.l, temp.size() - i - 1.l) * (temp[i] - L'0'));
else
throw std::invalid_argument("Invalid numerical string!");
if (s.find(L'-') != S::npos)
result = -T(std::fabs(result));
if (s.find(L'.') != S::npos && std::is_floating_point<T>::value)
result /= T(std::powl(10.l, s.size() - s.find(L'.') - 1.l));
return std::is_floating_point<T>::value ? T(result) : T(result + T(should_add));
}
Just use it like you typically would...
auto some_number = convert_string_to_number<float>(myString);...
For the floating point part of the assignment: what about regular expressions? It is also kind of built-in functionality, but general purpose, not designed for your particular task, so I hope your teacher will be fine with this idea.
You can use the following regex: [+-]?([0-9]*[.])?[0-9]+ (I got it from this answer) to detect if provided string is a floating point number. Then you can modify the expression a little bit to capture the +/- signs and parts before/after the dot separator. Once you extract these features the task should be relatively simple.
Also please change your method signature to: float convert(const std::string& str).
Try this :
int convert(char str[], int size) {
int number = 0;
for (int i = 0; i < size; ++i) {
number += (str[i] - 48)*pow(10, (size - i - 1));
}
return number;
}
int pow10(int radix)
{
int r = 1;
for (int i = 0; i < radix; i++)
r *= 10;
return r;
}
float convert2float(char str[], int size) { //size =6
// convert to string_without_decimal
char str_without_decimal[10];
int c = 0;
for (int i = 0; i < size; i++)
{
if (str[i] >= 48 && str[i] <= 57) {
str_without_decimal[c] = str[i];
c++;
}
}
str_without_decimal[c] = '\0'; //str_without_decimal = "12345"
//adjust size if dot present or not. If no dot present => size = c
size = (size != c ?) size - 1 : size; //size = 5 = 6-1 since dot is present
//convert to decimal
int decimal = convert(str_without_decimal, size); //decimal = 12345
//get divisor
int i;
for (i = size; i >= 0; i--) {
if (str[i] == '.') break;
}
int divisor = pow10(size - i); //divisor = 10;
return (float)decimal/(float) divisor; // result = 12345 /10
}
int main()
{
char str[] = "1234.5";
float f = convert2float(str, 6);
cout << f << endl;
return 0;
}

convert any base to base 10 in C++

I have this code:
#include <stdio.h>
#include <ctype.h>
int validnumber(int b, char* p);
unsigned long base2dec(int b,char *p);
void dec2base (int b,unsigned long x);
char *number;
main() {
int base,temp=0,count;
unsigned long Decimal_number;
do {
printf ("Give the base of the number you want to tranform:");
scanf ("%d", &base);
if (base<2 || base>16)
printf("Not acceptable base number, numbers should be in range from 2 to 16\n\n");
} while (base<2 || base>16);
printf ("Give the number you want to tranform:");
scanf("%s", number);
for (count=0;count<32;count++) {
number [count]= toupper(number[count]);
}
temp=validnumber(base, number);
if (temp==0)
printf ("O arithmpos pou eisagatai periexei MH egkira symbola\n");
else
if (temp==1)
printf ("O arithmpos pou eisagatai periexei egkira symbola\n");
if (temp==1) {
Decimal_number = base2dec( base , number);
}
int validnumber(int b, char *p){
int count, a[32];
for (count=0;count<32;count++)
a[count]=p[count];
if (b>=2 && b<=10) {
for (count=0;count<32;count++) {
if (a[count]<48 || a[count]>48+b)
return 0;
break;
}
}
if (b>=11 && b<=16) {
for (count=0;count<32;count++) {
if ((a[count]>=48 && a[count]<=57) || (a[count]>=65 && a[count]<=70)) {
return 1;
}
}
}
}
From this point the main program must call the function:
unsigned long base2dec (int b, char * p)
which accepts as arguments the base b and a pointer p in character table that
corresponds to the imported string s and returns the number representing the s expressed in the decimal system.
Also, it should call the function:
void dec2base (int b, unsigned long x)
which accepts as arguments the base b and the value of the number x in the decimal system and displays the base value and the representation of the number x in this base. The main program calls this function for all of the base values from 2 to 16.
Are there any ideas on how to begin? Any guidance will be appreciated.
In your base2dec, you will simply call this method and pass in 'b' as it is and x which should be the converted string.
Here is an implementation of dec2base. It is implemented recursively.
void dec2base(int b, unsigned long x){
if (x == 0)
return;
int y = x % b;
x /= b;
if (y < 0)
x += 1;
dec2base(b, x);
//converted digits to hex after realizing this solution doesn't work
//for bases greater than 10. Credits to Trevor pointing this out.
cout<< hex << y < 0 ? y + (b * -1) : y;
return;
}
First of all please have a look at your formatting because the way your code is written makes it harder than it needs to be to follow.
Here is what I would do:
#include <stdexcept>
#include <iostream>
void dec2base(int b, long x)
{
// Quick check for zero
if (x == 0)
{
std::cout << '0';
return;
}
// Print the negative sign if present, also negate
if (x < 0)
{
std::cout << '-';
x = -x;
}
char buf[12];
int i = 0;
// Convert to a backwards BCD
do {
buf[i++] = static_cast<char>(x % b);
} while (x /= b);
// Print it starting from the last digit (really the first)
do {
if (buf[--i] <= 9) std::cout << static_cast<char>(buf[i] + '0');
else std::cout << static_cast<char>(buf[i] + ('a' - 10));
} while (i);
}
long base2dec(int b, char * p)
{
long digit; // Current digit
long mul = 1; // Current multiplier
char *pos = p; // Current position
bool neg = false; // Sign
long ret = 0; // The return value
// Find the last digit
while (*pos) pos++;
// Continue until the start of the string is reached
while (pos-- != p)
{
if (*pos < '0')
{
if (*pos == '-')
{
// Sign reached, save it an break out
neg = true;
break;
}
else // Shouldn't happen
{
throw std::invalid_argument("Not a number");
}
}
if (*pos > 'f')
throw std::invalid_argument("Not a number");
// Get a digit
if (*pos <= '9') digit = *pos - '0';
else if (*pos >= 'a') digit = *pos - ('a' - 10);
else if (*pos >= 'A' && *pos <= 'F')
digit = *pos - ('A' - 10);
else
throw std::invalid_argument("Not a number");
// Make sure it is not larger than or equal to the base
if (digit >= b)
throw std::invalid_argument("Not a number");
// Add the digit
ret += digit * mul;
// Increase the multiplier
mul *= b;
}
return neg ? -ret : ret;
}
int main()
{
long val = base2dec(16, "123f");
dec2base(16, val);
return 0;
}
I realize you didn't ask for a signed version but as it is very easy to implement I have done it. If you really don't need to deal with signed values it is simple to drop the relevant parts from the functions.
This is a very quick and dirty go at this and this could no doubt be improved both for readability and performance but is, I think, a good starting point.
Here is a slightly improved version of base2dec():
long base2dec(int b, char * p)
{
long digit; // Current digit
bool neg = false; // Sign
long ret = 0; // The return value
// Check for negative number
if (*p == '-')
{
neg = true;
p++;
}
// Continue until the end of the string is reached
for (; *p != 0; p++)
{
// Rough range check
if (*p < '0' || *p > 'f')
throw std::invalid_argument("Not a number");
// Get a digit
if (*p <= '9') digit = *p - '0';
else if (*p >= 'a') digit = *p - ('a' - 10);
else if (*p >= 'A' && *p <= 'F')
digit = *p - ('A' - 10);
else
throw std::invalid_argument("Not a number");
// Make sure it is not larger than or equal to the base
if (digit >= b)
throw std::invalid_argument("Not a number");
// Add the digit
ret = ret * b + digit;
}
return neg ? -ret : ret;
}
Regarding the validnumber() function. This check is best performed during the conversion both to avoid having to read the entire string twice and because base2dec() really ought to check for valid input anyway. If you still need a separate check then you need to fix validnumber(). There is no need to copy the string to an array and it is also better to use the same code for all bases. Here is a suggestion:
bool validnumber(int b, char *p)
{
// Check for valid base
if (b < 2 || b > 16) return false;
// Extract numeric and alpha parts of the base
int b_numeric = b <= 10 ? b : 10;
int b_alpha = b - 11;
// Ignore any sign
if (*p == '-') p++;
// Continue until the end of the string
for (; *p != 0; p++)
{
// Digits < 0 are always bad
if (*p < '0') return false;
// Check for valid numeric digits
if (*p > ('0' + b_numeric))
{
// Check for valid alpha digits
if (b <= 10) return false;
if (*p < 'A' || *p > ('a' + b_alpha)) return false;
if (*p > ('A' + b_alpha) && *p < 'a') return false;
}
}
return true;
}

Conver BCD Strings to Decimal

I am looking for better ways to optimize this function for better performance, speed its targeted towards embedded device. i welcome any pointers, suggestion thanks
function converts string BCD to Decimal
int ConvertBCDToDecimal(const std::string& str, int splitLength)
{
int NumSubstrings = str.length() / splitLength;
std::vector<std::string> ret;
int newvalue;
for (auto i = 0; i < NumSubstrings; i++)
{
ret.push_back(str.substr(i * splitLength, splitLength));
}
// If there are leftover characters, create a shorter item at the end.
if (str.length() % splitLength != 0)
{
ret.push_back(str.substr(splitLength * NumSubstrings));
}
string temp;
for (int i=0; i<(int)ret.size(); i++)
{
temp +=ReverseBCDFormat(ret[i]);
}
return newvalue =std::stoi(temp);
}
string ReverseBCDFormat(string num)
{
if( num == "0000")
{
return "0";
}
else if( num == "0001")
{
return "1";
}
else if( num == "0010")
{
return "2";
}
else if( num == "0011")
{
return "3";
}
else if( num == "0100")
{
return "4";
}
else if( num == "0101")
{
return "5";
}
else if( num == "0110")
{
return "6";
}
else if( num == "0111")
{
return "7";
}
else if( num == "1000")
{
return "8";
}
else if( num == "1001")
{
return "9";
}
else
{
return "0";
}
}
Update
this is what i plan to get, for a BCD Value::0010000000000000 Decimal Result 2000
BCD is a method of encoding decimal numbers, two to a byte.
For instance 0x12345678 is the BCD representation of the decimal number 12345678. But, that doesn't seem to be what you're processing. So, I'm not sure you mean BCD when you say BCD.
As for the code, you could speed it up quite a bit by iterating over each substring and directly calculating the value. At a minimum, change ReverseBCDFormat to return an integer instead of a string and calculate the string on the fly:
temp = temp * 10 + ReverseBCDFormat(...)
Something like that.
What you call BCD is not actually BCD.
With that out of the way, you can do this:
int ConvertBCDToDecimal(const std::string& str, int splitLength)
{
int ret = 0;
for (unsigned i = 0, n = unsigned(str.size()); i < n; )
{
int v = 0;
for (unsigned j = 0; j < splitLength && i < n; ++j, ++i)
v = 2*v + ('1' == str[i] ? 1 : 0); // or 2*v + (str[i]-'0')
ret = 10*ret + v;
}
return ret;
}
Get rid of all the useless vector making and string copying. You don't need any of those.
Also, I think your code has a bug when processing strings with lengths that aren't a multiple of splitLength. I think your code always considers them to be zero. In fact, now that I think about it, your code won't work with any splitLength other than 4.
BTW, if you provide some sample inputs along with their expected outputs, I would be able to actually verify my code against yours (given that your definition of BCD differs from that of most people, what your code does is not exactly clear.)
as soon as you're optimizing function, here is different variant:
int ConvertBCDToDecimal(const std::string& str) {
unsigned int result = 0;
const std::string::size_type l = str.length();
for (std::string::size_type i = 0; i < l; i += 4)
result = result * 10 + ((str[i] - '0') << 3) + ((str[i + 1] - '0') << 2) + ((str[i + 2] - '0') << 1) + (str[i + 3] - '0');
return result;
}
note: you don't need splitLength argument, as you know that every digit is 4 symbols

How should I approach a credit card number validation algorithm?

I'm writing a program to validate credit card numbers and I have to use Luhn's Algorithm. Let me say beforehand, that I have just started to learn to program (we covered loops like last week), so there a lot of things I am unfamiliar with. I am having trouble with one of my functions that checks the arithmetic. Basically, it has to double every second digit from right to left and add everything together. But if you double a number, like 5, and you get 10, then you will have to add 1+0=1 to the total sum instead of 10. That's the part I'm stuck on. How can I put that in a program?
Sample code so far:
int
doubleEvenSum(string creditCardNumber) {
int evenSum;
int countPosition;
int doublePosition;
int length;
length = creditCardNumber.length ();
countPosition = creditCardNumber.at(length - 2);
evenSum = 0;
while(countPosition>0) {
if ((2 * countPosition) < 10) {
doublePosition = 2 * countPosition;
}
else if ((2 * countPosition) > 9) {
???
}
evenSum = evenSum + doublePosition;
}
#include <stdio.h>
#include <string.h>
#include <ctype.h>
/*
return the Luhn (MOD10) checksum for a sequence of digits.
-1 is returned on error (a non-digit was in the sequence
*/
int mod10( char const* s)
{
int len = strlen(s);
int sum = 0;
int dbl = 0;
while (len) {
char digit;
int val;
--len;
digit = s[len];
if (!isdigit( (unsigned char) digit)) return -1; // non digit in the sequence
val = digit - '0'; // convert character to numeric value
if (dbl) {
// double the value
val *= 2;
// if the result is double-digits, add the digits together
if (val > 9) {
val = val - 10;
val = val + 1;
}
}
dbl = !dbl; // only double value every other time
sum += val;
}
return sum % 10;
}
Here is a different algorithm. I cut/pasted from a C# example; the second link discusses a number of optimization for Luhn.
Please study this example, and please run it through the debugger to study how the code behaves as it's executing. Understanding how code actually runs (as opposed to how you think it will run when you write it) is an essential skill. IMHO....
/*
* Validate credit card with Luhn Algorithm
*
* REFERENCES:
* - http://jlcoady.net/c-sharp/credit-card-validation-in-c-sharp
* - http://orb-of-knowledge.blogspot.com/2009/08/extremely-fast-luhn-function-for-c.html
*/
#include <stdio.h> // printf(), scanf(), etc
#include <string.h> // strlen (), etc
#include <ctype.h> // isdigit(), etc
#if !defined(FALSE)
#define FALSE 0
#define TRUE ~FALSE
#endif
/*
* type definitions (should go in separate header)
*/
enum CardType {
MASTERCARD=1, BANKCARD=2, VISA=3, AMEX=4, DISCOVER=5, DINERS=6, JCB=7
};
/*
* function prototypes (should also go in header)
*/
int luhn (int number[], int len);
bool validate (CardType cardType, char *cardNumber);
/*
* program main
*/
int
main (int argc, char *argv[])
{
char cc_number[80];
int cc_type;
for ( ;; ) {
printf ("Enter a credit card number and type (1, 2, 3, 4, 5. 6 or 7):\n");
printf (" MASTERCARD=1, BANKCARD=2, VISA=3, AMEX=4, DISCOVER=5, DINERS=6, JCB=7\n");
int iret = scanf ("%s %d", cc_number, &cc_type);
if (iret == 2)
break;
else
printf ("Incorrect input: please enter a valid CC# and CC type\n");
}
if (validate ((CardType)cc_type, cc_number))
printf ("Valid\n");
else
printf ("Invalid card type/number\n");
return 0;
}
/*
* validate card#
*/
bool
validate (CardType cardType, char *cardNumber)
{
// 16 or fewer digits?
int len = strlen(cardNumber);
if (strlen (cardNumber) > 16)
return false;
// number to validate
int number[16];
for(int i = 0; i < (int)strlen (cardNumber); i++) {
if(!isdigit(cardNumber[i]))
return FALSE;
number[i] = cardNumber[i] - '0';
}
// Validate based on card type, first if tests length, second tests prefix
switch(cardType) {
case MASTERCARD:
if(len != 16)
return FALSE;
if(number[0] != 5 || number[1] == 0 || number[1] > 5)
return FALSE;
break;
case BANKCARD:
if(len != 16)
return FALSE;
if(number[0] != 5 || number[1] != 6 || number[2] > 1)
return FALSE;
break;
case VISA:
if(len != 16 && len != 13)
return FALSE;
if(number[0] != 4)
return FALSE;
break;
case AMEX:
if(len != 15)
return FALSE;
if(number[0] != 3 || (number[1] != 4 && number[1] != 7))
return FALSE;
break;
case DISCOVER:
if(len != 16)
return FALSE;
if(number[0] != 6 || number[1] != 0 || number[2] != 1 || number[3] != 1)
return FALSE;
break;
case DINERS:
if(len != 14)
return FALSE;
if(number[0] != 3 || (number[1] != 0 && number[1] != 6 && number[1] != 8) || number[1] == 0 && number[2] > 5)
return FALSE;
break;
case JCB:
if(len != 16 && len != 15)
return FALSE;
if(number[0] != 3 || number[1] != 5)
return FALSE;
break;
default:
return FALSE;
}
int sum = luhn (number, len);
return (sum % 10 == 0);
}
// Use Luhn Algorithm to validate
int luhn (int number[], int len)
{
int sum = 0;
for(int i = len - 1; i >= 0; i--)
{
if(i % 2 == len % 2)
{
int n = number[i] * 2;
sum += (n / 10) + (n % 10);
}
else
sum += number[i];
}
return sum;
}
int luhnCardValidator(char cardNumbers[]) {
int sum = 0, nxtDigit, i;
for (i = 0; cardNumbers[i] != NULL_TERMINATOR ; i++) {
nxtDigit = cardNumbers[i] - START_OF_ASCII_NUMERIC;
if (i % 2 == 0)
nxtDigit = (nxtDigit > 4) ? (nxtDigit * 2 - 10) + 1 : nxtDigit * 2;
sum += nxtDigit;
}
return (sum % 10);
}
This:
... (nxtDigit > 4) ? (nxtDigit * 2 - 10) + 1 : ...
is the clever bit. If the digit is greater than 4, then the doubling will be 10 or more. In that case, you take the doubled number and subtract 10 which will give you the ones-digit then you add 1 (the tens-digit).
Just subtract 9 from the double of the number then you will equivalent of the sum of the digits.
For ex.
7= 7*2 = 14 = 1+4 = 5 OR 14-9 = 5
This is more efficient than writing code for adding both digits.