I'm trying to solve the following problem, which how to add two strings without converting them to integer. I have found a solution to the problem, but I don't understand it. Would someone explain it in plain english please ?
here is the code :
class Solution {
public:
string addStrings(string num1, string num2) {
int i=num1.size()-1,j=num2.size()-1,carry=0;
string res="";
while(i>=0||j>=0)
{
if(i>=0) carry+=num1[i--]-'0';
if(j>=0) carry+=num2[j--]-'0';
res=to_string(carry%10)+res;
carry/=10;
}
return carry?"1"+res:res;
}
};
Okay! Lemme explain to you. Numbers are from 0-9. So, maximum sum possible is <=18. So, we need to take a flag/count/carry dummy variable which will be 1 when our sum exceeds 10 (num1[i]-'0'+num2[i]-'0'>=10).
When we add two numbers we start from the end. Same here we will loop from end to start i.e. while(i>=0 or j>=0 or count). Count is in while statement 'coz what if i=0 &/| j=0 sum is more than 10 then we will need to add an extra one to the start of the string.
Add elements from both strings and decrement corresponding counter i--, j--. Add carry either 0 or 1. calculate new carry which will be passed on to the next sum calculation. Take modulo of sum as we want a single digit. Covert it into string and append to res.
My Code
class Solution {
public:
string addStrings(string num1, string num2) {
int n1 = num1.size(), i = n1 - 1;
int n2 = num2.size(), j = n2 - 1;
int carry = 0;
string res = "";
while(i>=0 || j>=0 || carry){
long sum = 0;
if(i >= 0){sum += (num1[i] - '0');i--;}
if(j >= 0){sum += (num2[j] - '0');j--;}
sum += carry;
carry = sum / 10;
sum = sum % 10;
res = to_string(sum) + res;
}
return res;
}
};
Related
I tried to solve Multiply Strings by c++ by this approach, but I cannot avoid integer overflow by change type from int to long long int or double. Python won't overflow, so my code works like below.
Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2, also represented as a string.
Python works:
class Solution:
def multiply(self, num1: str, num2: str) -> str:
n = len(num1) # assume n >= m
m = len(num2)
if n < m:
num1, num2 = num2, num1
n, m = m, n
product = 0
for i in range(1, m + 1):
multiplier = int(num2[m - i]) # current character of num2
sum_ = 0
for j in range(0, n): # multiply num1 by multiplier
multiplicand = int(num1[n - j - 1])
num = multiplicand * (10 ** j) * multiplier
sum_ += num
product += sum_ * (10 ** (i - 1))
return str(product)
C++ failed:
string multiply(string num1, string num2) {
int n = num1.size();
int m = num2.size();
if (n < m) {
std::swap(num1, num2);
std::swap(n, m);
}
long long int product = 0;
for (int i = 1; i <= m; ++i) {
int multiChar = num2[m - i] - '0';
long long int sum = 0;
for (int j = 0; j < n ; ++j) {
int charCand = num1[n - j - 1] - '0';
long long int num = charCand * ((pow(10, j))) * multiChar;
sum += num;
}
product += sum * ((pow(10, i - 1)));
}
return std::to_string(product);
}
As far as I have tested, some cases are OK, but overflow seems unavoidable if the number is too big. Is there any way to fix my code?
Testcase:
"12323247989"
"98549324321"
runtime error: 1.05355e+20 is outside the range of representable values of type 'long long' (solution.cpp)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:28:17
Expected:
"1214447762756072040469"
You are not on the right way. Imagine how you would do that by hand:
abc*def
-------
xxxx
xxxx0
xxxx00
-------
You just add single digits as well, don't you? Only those of same significance – possibly considering some carry.
You might rather reproduce the same in code, too. Producing overflow that way is much less likely (I assume that after multiplying single digits summing up the results in a single integer – recommending an unsigned type for – is acceptable; if not, you'd have to build up a std::string again). The sign you calculate independently, just as you'd do by hand as well.
One difference to multiplication by hand we'll have, though: By hand you would create rather large intermediate numbers by multiplying one number with each digit
of the other number. That would require to store these intermediate numbers as strings again, e. g. in a vector. More efficient, though, is identifying those digit pairs of which the multiplication results in the same significance.
These will be 0|0 -> 0; 0|1, 1|0 -> 1; 0|2, 1|1, 2|0 -> 2, and so on. You produce these pairs by:
for(size_t i = 0, max = std::max(num1.length(), num2.length); i < max; ++i)
{
for(size_t j = 0; j < i; ++j)
{
if(j < num1.length() && i - j < num2.length())
{
// iterate backwards for easy carry handling
size_t idx1 = num1.length() - j;
size_t idx2 = num2.length() - (i - j);
// multiply characters at num1[idx1] and num2[idx2] and add result to sum
}
}
// add carry
// calculate last digit and a p p e n d to a result string
// update carry
}
// append '-' sign, if result is negative
std::reverse(result.begin(), result.end());
Building up the string in reverse order is more efficient, as you do not need to move the subsequent characters all the time. (Untested code, if you find a bug, please fix it yourself).
The loops are in my preferred variant; if you feel better with another, feel free to change; just be aware that with signed types you can produce endless loops if you try e. g. for(unsigned i = n; n >= 0; --i /* overflows to UINT_MAX */).
Side note: You should accept the input strings by reference (std::string const& num1, std::string const& num2), that avoids the needless copies arising by accepting by value.
I am working on a function called add(BigDecimals c) which keeps getting an error that not all control paths are returning a value:
BigDecimal BigDecimal::add(BigDecimal c)
{
string fFirst = to_string(this->fraction()); //fraction part of the first number
string fSecond = to_string(c.fraction()); //fraction part of the second number
if (fFirst.length() < fSecond.length()) //fraction part of first/second number
{
string str(this->toString()); //convert fraction to string
for (unsigned int i = 0; i < fFirst.length() - fSecond.length(); i++) //difference between first and second
{
str += "0"; //pad in the 0's
}
this->equals(str); //call the equals function
}
if (fSecond.length() < fFirst.length()) //flip numbers around, second < first
{
string str(this->toString()); //convert fraction to string
for (unsigned int i = 0; i < fSecond.length() - fFirst.length(); i++) //difference between second and first
{
str += "0"; //pad in the 0's
}
this->equals(str); //call the equals function
}
for (unsigned int i = fSecond.length(); i > 0; i++)
{
int carryFlag = 0; //carry flag set to 0
int sum = carryFlag + stoi(this->at(i).toString()) + stoi(c.at(i).toString());
if (sum >= 10) //greater than 10
{
carryFlag = 1;
sum = sum % 10;
}
else //less than 10
{
carryFlag = 0; //set carry flag to 0
}
return BigDecimal(to_string(sum)); //this is the only thing I want to
//return
}
//It wants to return something here, but I am not sure what.
}
I have tried to fix this by replacing if statements with else statements, but nothing really works. I have no idea how to fix this error, so any help is appreciated!
Your logic is flawed (and the error message and the fact you don't know what to do about it is a good indication of that).
Your code will always return on the first iteration of the loop. Clearly what you want to do is accumulate a digit string one digit at a time, but that's not what the code you've written does.
This is something more like what you want. However I think you have other errors to do with the padding of numbers, so this code isn't going to work, but hopefully will give you some idea.
string result = "";
int carryFlag = 0; //carry flag set to 0
for (unsigned int i = fSecond.length(); i > 0; i--)
{
int sum = carryFlag + stoi(this->at(i).toString()) + stoi(c.at(i).toString());
if (sum >= 10) //greater than 10
{
carryFlag = 1;
sum = sum % 10;
}
else //less than 10
{
carryFlag = 0; //set carry flag to 0
}
result = to_string(sum) + result;
}
if (carryflag)
result = "1" + result;
return BigDecimal(result);
Notice the return is only after the loop has finished, and a new variable called result accumulates the digit generated each time round the loop.
Also notice the carryflag variable has been moved outside of the loop. The whole point of the carry is to hold the carry from one iteration of the loop to the next, so it can't be inside the loop. Also if there is a carry left over after all the digits have been added, you need to add a one digit to the beginning of the result.
Also I've changed i++ to i-- in the loop. You are iterating backwards through the strings you are adding so you need i--. It's an improvment but as I said before I still think this loop is wrong.
Clearly you understand how to do long addition, but what you haven't mastered yet is how to translate that into code. You have to think very carefully and precisely about what you are asking the computer to do.
So, I started learning C++ recently. This code is trying to add the sum of the squares of each numbers digits. For example: 243: 2*2 + 4*4 + 3*3 = 29.
int sumOfSquareDigits(int n) //BUG WITH INPUT OF 10, 100, 1000, etc.
{
int digits = findDigits(n);
int number;
int remainder;
int *allDigits = new int[digits];
for (int i = 0; i < digits; i++) { //assigns digits to array
if (i + 1 == digits){ //sees if there is a ones value left
allDigits[i] = n;
}
else {
remainder = (n % findPower10(digits - (i + 1)));
number = ((n - remainder) / findPower10(digits - (i + 1)));
allDigits[i] = number; //records leftmost digit
n = n - (allDigits[i] * findPower10(digits - (i + 1))); //gets rid of leftmost number and starts over
}
}
int result = 0;
for (int i = 0; i < digits; i++) { //finds sum of squared digits
result = result + (allDigits[i] * allDigits[i]);
}
delete [] allDigits;
return result;
}
int findDigits(int n) //finds out how many digits the number has
{
int digits = 0;
int test;
do {
digits++;
test = findPower10(digits);
} while (n > test);
return digits;
}
int findPower10(int n) { //function for calculating powers of 10
int result = 1;
for (int i = 0; i < n; i++)
result = result * 10;
return result;
}
And after running the code, I've figured out that it (barely) mostly works. I've found that whenever a user inputs a value of 10, 100, 1000, etc. it always returns a value of 100. I'd like to solve this only using the iostream header.
Sorry if my code isn't too readable or organized! It would also be helpful if there are any shortcuts to my super long code, thanks!
The problem is in the findDigits function. For the values 10, 100, 1000 etc, it calculates the number of the digits minus one. This happens because of the comparison in the loop, you are stopping when n is less or equal to test, but in these cases n is equal test and you should run the next iteration.
So, you should change the line 33:
} while (n > test);
to:
} while (n >= test);
Now, it should work just fine. But it will not work for negative numbers (I don't know this is required, but the solution bellow works for that case too).
I came up with a much simpler solution:
int sumOfSquareDigits(int n)
{
// Variable to mantain the total sum of the squares
int sum = 0;
// This loop will change n until it is zero
while (n != 0) {
/// The current digit we will calculate the square is the rightmost digit,
// so we just get its value using the mod operator
int current = n % 10;
// Add its square to the sum
sum += current*current;
// You divide n by 10, this 'removes' one digit of n
n = n / 10;
}
return sum;
}
I found the problem challenging managed to reduce your code to the following lines:
long long sumOfSquareDigits(long long i) {
long long sum(0L);
do {
long long r = i % 10;
sum += (r * r);
} while(i /= 10);
return sum;
}
Haven't test it thoroughly but I think it works OK.
I am going to have an array that is 50 elements long. Each element will contain one digit to form a 50 digit number. What I want to do is multiply this 50 digit long array by another 50 digit long array. The way I thought of doing this was converting each number to form one string. Then produce an algorithm that would multiply line by line 20 digits at a time. Then once the last for loop breaks out of scope, I could reconstruct the new array, digit by digit from converting it from a string. Any alternate ideas before I attempt this, or is what I got what you would do too?
int n1[50], n2[50], out[51];
// n1 and n2 must be populated here
int carry = 0;
for (int cur = 49; cur >= 0; --cur) {
out[cur+1] = n1[cur] * n2[cur] + carry;
carry = out[cur+1] / 10;
out[cur+1] %= 10;
}
out[0] = carry;
I believe you could find the question at leetcode OJ named "Multiply Strings".
This is my solution. Just for reference. Wish this will help :)
class Solution {
public:
string multiply(string num1, string num2) {
int s1(num1.size()), s2(num2.size()), size(s1+s2);
vector<int> digit(size,0), carry(size,0); // digit: store current digit, carry: store carry digit
for(int i = 0; i < s1; ++i){
for(int j = 0; j < s2; ++j){
int mul = num1[s1-1-i]-'0';
int muled = num2[s2-1-j]-'0';
int tmp = mul*muled;
digit[size-1-i-j] += tmp%10; // accum
carry[size-1-i-j-1] += tmp/10; // accum
}
}
int carrFlag(0); // initial carry_flag
for(int i = size-1; i >= 0; --i){ // merge digit and carry
int sum = digit[i] + carry[i] + carrFlag;
ret.insert(ret.begin(),1,'0'+sum%10); // compose result string
carrFlag = sum/10; // update carry_flag
}
int pos(0);
while(ret[pos] == '0') ++pos; // get rid of extra 0's
if(pos>=size) return "0"; // edge case
return ret.substr(pos);
}
private:
string ret;
};
Can you help me please? I try to do with while statement but I could not write the program.
Given an integer for example 12564897 and the program must show it 1-2-5-6-4-8-9-7
How do you detect in C++. Thanks a lot.
I tried with five digits integer.
int z,y,x,result,number1,number2,number3,number4,number5;
cout<<"Enter a five digit integer: ";
cin>>result; //read number
cout<<"The number is: "<<result<<endl;
number1 = result / 10000;
x = result / 1000;
number2 = x % 10;
y = result / 100;
number3 = y % 10;
z = result / 10;
number4 = z % 10;
number5 = result % 10;
cout<<"digits are: "<<number1<<"-"<<number2<<"-"<<number3<<"-"<<number4<<"-"<<number5<<endl;
system("pause");
return 0;
}
I think the smartest way is create a loop that divide by ten ( or the base ) and print the remainder, then divide by ten and do again. In preudo code:
let a = input
let base = 10
do
{
store a mod base in result
a = (integer) a / base;
}while(a>0)
print result reversed
mod is the remainder operator ( % in C/C++ )
please note thad by changing base you can have the digit in any representation of the number
Convert your Integer to a string and then print every character of that string with a - in between.
This is snippet from program which print out integer in reverse order.
You can modify it to fits your need (it's your homework)
//Read input number
cin >> dInput;
//Calculate log10
int logValue = (int)log10(dInput);
//Iteration through n-th power of 10
for(int i = logValue; i >= 0; i--) {
//Calculate actual power of 10
double d = pow(10,(double)i);
int n = (int)dInput / d;
//Subtract remainder from previous number
dInput -= (n * d);
//Print out "-"
cout << n;
if(i != 0) << "-";
}
I thought about writing the code itself, but since it's a homework, I'll give you the idea and let you code it
First, you'll convert that integer to a string using sprintf function
Then you'll make an integer having the size of the string. Let it be S
Then you'll make a for loop,
i=1, i < S, i+=2
i starts from 1 as the - is put after the first character
In that loop, you would insert the - character at the position of i, then you'll update integer S with the size. If you didn't update it, the following (for example) would happen
12345 (size = 5)
1-2345 (size = 5, real size = 6)
1-2-345 (size = 5, real size = 7)
It would stop here. As the condition i<5 would fail
That's all. Good luck.
OK, since everyone else has had a go, this is my attempt:
void outInt(int inInt){
int dividend;
dividend=inInt/10;
if (dividend!=0){
outInt(dividend);
cout<<"-"<<inInt%10;
}
else
cout<<(inInt);
};
No 'print result reversed' required. Should work for 0 and not print any '-' for numbers less than 10.