I am writing a decimal multiplier in C++. The multiplier is implemented by taking two integers represented as vectors of digits. Each vector stores its digits in reverse order, for easier representation by powers of ten. For example, 3497 = 3 * 10^3 + 4 * 10^2 + 9 * 10^1 + 7 *10^0 and is stored in a vector as {7, 9, 4, 3}. Thus, each index of the vector represents that digit’s respective power of ten in the integer.
However, I’m having some bugs in my multiplication. 1-digit x 1-digit and 2-digit x 1-digit multiplication work perfectly, but it breaks down at 2-digit x 2-digit. I’m fairly certain that fixing this bug would fix all the other bugs with n-digit x m-digit. My code for both my multiplication and addition methods are below.
vector<int> multiply(vector<int> &a, vector<int> &b) {
// check for emptiness
if(a.size() == 0)
return b;
else if(b.size() == 0)
return a;
unsigned int i; // increment counter
// compensate for size differences
if(a.size() > b.size())
for(i = 0; i < a.size()-b.size(); ++i)
b.push_back(0);
else
for(i = 0; i < b.size()-a.size(); ++i)
a.push_back(0);
int c = 0; // carry value
int temp; // temporary integer
vector<int> p; // product vector
vector<int> s; // sum vector
s.push_back(0); // initialize to 0
// multiply each digit of a by an index of b
for(i = 0; i < b.size(); ++i) {
// skip digits of 0
if(b[i] == 0)
continue;
p.resize(i,0); // resize p and add 0s
// multiply b[i] by each digit of a
for(unsigned int j = 0; j < a.size(); ++j) {
temp = c + b[i] * a[j]; // calculate temporary value
// two cases
if(temp > 9) {
c = temp / 10; // new carry
p.push_back(temp % 10);
}
else {
c = 0;
p.push_back(temp);
}
}
// append carry if relevant
if(c != 0)
p.push_back(c);
// sum p and s
s = add(p, s);
p.clear(); // empty p
}
return s; // return summed vector (total product)
}
vector<int> add(vector<int> &a, vector<int> &b) {
// check for emptiness
if(a.size() == 0)
return b;
else if(b.size() == 0)
return a;
unsigned int i; // increment counter
// compensate size differences
if(a.size() > b.size())
for(i = 0; i < a.size()-b.size(); ++i)
b.push_back(0);
else
for(i = 0; i < b.size()-a.size(); ++i)
a.push_back(0);
int c = 0; // carry value
vector<int> s; // sum vector
int temp; // temporary value
// iterate through decimal vectors
for(i = 0; i < a.size(); ++i) {
temp = c + a[i] + b[i]; // sum three terms
// two cases
if(temp > 9) {
c = temp / 10; // new carry
s.push_back(temp % 10); // push back remainder
}
else {
c = 0;
s.push_back(temp);
}
}
// append carry if relevant
if(c != 0)
s.push_back(c);
return s; // return sum
}
A few test cases:
45 * 16 returns 740 (should be 720)
34 * 18 returns 542 (should be 532)
67 * 29 returns 2003 (should be 1943)
28 * 12 returns 336 (correct)
The only problem I could think of would be an issue with the carries, but everything seems to check out as I walk through the code. Can anyone see the error? Or am I taking the wrong approach to this entirely?
You’re not clearing out the carry before (or after) the inner loop.
Also, in
addyou probably want:As-is, you’ll only be pushing a number of zeroes equal to (I believe) half of the initial difference between the arrays. Try an interactive debugger (as James suggests) and you may turn up other bugs (though there’s also something to be said for running code as short as this by hand).