我正在尝试使用c-strings创建一个包含(在理论上)无限数量的数字的类,因为int有一个限制。我在乘法方面遇到了很多麻烦,并开始迷惑自己。我是学生,所以我没有抓到的任何帮助和错误都非常感激。我现在已经玩了4个小时的倍增。
目前的问题是我正在计算结果(如果你尝试x = 12和y = 4,我只能得到8,那么最后的答案变成了7,这是奇怪的)但它不是妥善存放。
定义:
MyInt operator* (const MyInt& x, const MyInt& y)
{
MyInt steps[x.numDigits - 1]; // Create an array of MyInts
int carry = 0; // Holds the 'carry the one'
int result, xInt, yInt; // For adding old-school
// Add each digit separately.
for (int i = 0; i < x.numDigits; i++)
{
steps[i].numDigits = y.numDigits; // set the numDigits to y's
// Resize the array to the size of numDigits
steps[i].Resize(steps[i].numDigits);
cout << "x.numDigits = " << x.numDigits << '\n'; // DELETE THESE
cout << "numDigits = " << steps[i].numDigits << '\n';
// Figure out xInt's value
xInt = C2I(x.myNumber[x.numDigits - i - 1]);
// Now multiply xInt by each digit of y
for (int j = 1; j <= y.numDigits; j++)
{
// yInt's value for this run through
yInt = C2I(y.myNumber[y.numDigits - j]);
// Answer is xInt * yInt + the remainder
result = ((xInt * yInt) + carry);
carry = 0; // Reset carry to zero
// If the result is 10 or higher, carry the excess
if (result > 9)
{
carry = result / 10;
result = result % 10;
}
// Assign result to the appropriate slot in the new number
steps[i].myNumber[(steps[i].numDigits - j)] = I2C(result);
cout << "ASSIGNED " << steps[i].myNumber[steps[i].numDigits - j] //DELETE THESE
<< " TO SLOT " << (steps[i].numDigits - j)
<< " with a rem = " << carry << '\n';
}
cout << "YOU GOT OUT OF THE J FOR LOOP\n";
// If carry wasn't reset to 0, that means the loop ended.
// This means there is a # that cannot fit in the current
// array size. We must resize, and then assign
// the extra characters into the array.
if (carry > 0)
{
int carryCopy = carry; // Copy of n for counting numDigits
int carryCount = 0; // Counts up how many digits are in carry
while(carryCopy > 0) // Figure out how many #'s there are
{
carryCopy = carryCopy / 10;
carryCount++;
}
// Figure out the new size
steps[i].numDigits = steps[i].numDigits + carryCount;
// Resize to new size
steps[i].Resize(steps[i].numDigits + carryCount);
// Copy in the new digits
for (int k = carryCount-1; k >= 0; k--)
{
steps[i].myNumber[k] = I2C(carry % 10);
carry = carry / 10;
}
}
}
cout << "What you have so far is " << steps[0] << "\n"; // DELETE
cout << "YOU GOT TO THE ADDING PART\n"; // DELETE
MyInt r = 0; // Create MyInt for total result
// Add up all of the arrays in steps[] into r
for (int l = 0; l < x.numDigits - 1; l++)
r = r + steps[l];
return r; // Result
}
标头文件
#include <iostream>// for ostream, istream
using namespace std;
class MyInt
{
// these overload starters are declared as friend functions
friend MyInt operator+ (const MyInt& x, const MyInt& y);
friend MyInt operator* (const MyInt& x, const MyInt& y);
friend bool operator< (const MyInt& x, const MyInt& y);
friend bool operator> (const MyInt& x, const MyInt& y);
friend bool operator<= (const MyInt& x, const MyInt& y);
friend bool operator>= (const MyInt& x, const MyInt& y);
friend bool operator== (const MyInt& x, const MyInt& y);
friend bool operator!= (const MyInt& x, const MyInt& y);
friend ostream& operator<< (ostream& s, const MyInt& n);
friend istream& operator>> (istream& s, MyInt& n);
public:
MyInt(int n = 0); // first constructor
MyInt(const char * n); // second constructor
~MyInt(); // Destructor
MyInt(const MyInt & n); // Copy Constructor
MyInt& operator= (const MyInt & n); // Assignment operator
// be sure to add in the second constructor, and the user-defined
// versions of destructor, copy constructor, and assignment operator
private:
// member data (suggested: use a dynamic array to store the digits)
unsigned int numDigits; // The number of digits in myInt
char * myNumber; // Pointer to dynamic array of digits
void Resize(unsigned int newSize); // Resize array
};
和我用来测试的主程序:
int main()
{
// demonstrate behavior of the two constructors and the << overload
MyInt x(12345), y("9876543210123456789"), r1(-1000), r2 = "14H67", r3;
char answer;
cout << "Initial values: \nx = " << x << "\ny = " << y
<< "\nr1 = " << r1 << "\nr2 = " << r2 << "\nr3 = " << r3 << "\n\n";
// demonstrate >> overload
cout << "Enter first number: ";
cin >> x;
cout << "Enter second number: ";
cin >> y;
cout << "You entered:\n";
cout << " x = " << x << '\n';
cout << " y = " << y << '\n';
// demonstrate assignment =
cout << "Assigning r1 = y ...\n";
r1 = y;
cout << " r1 = " << r1 << '\n';
// demonstrate comparison overloads
if (x < y) cout << "(x < y) is TRUE\n";
if (x > y) cout << "(x > y) is TRUE\n";
if (x <= y) cout << "(x <= y) is TRUE\n";
if (x >= y) cout << "(x >= y) is TRUE\n";
if (x == y) cout << "(x == y) is TRUE\n";
if (x != y) cout << "(x != y) is TRUE\n";
// demonstrating + and * overloads
r1 = x + y;
cout << "The sum (x + y) = " << r1 << '\n';
r2 = x * y;
cout << "The product (x * y) = " << r2 << "\n\n";
cout << "The sum (x + 12345) = " << x + 12345 << '\n';
cout << "The product (y * 98765) = " << y * 98765 << '\n';
}
答案 0 :(得分:2)
你先做所有的乘法,然后是加法。这样效率很低,会使您的代码更加复杂。
相反,您应该在计算每个乘法阶段时将结果添加到一起。
例如,而不是:
A = 123
B = 456
S[0] = A * (B[2] * 10^2) = 123 * 400 = 49200
S[1] = A * (B[1] * 10^1) = 123 * 50 = 6150
S[2] = A * (B[0] * 10^0) = 123 * 6 = 738
R = S[0] + S[1] + S[2] = 49200 + 6150 + 738 = 56088
这样做:
A = 123
B = 456
R = 0
R += A * (B[2] * 10^2) = 0 + 123 * 400 = 49200
R += A * (B[1] * 10^1) = 49200 + 123 * 50 = 55350
R += A * (B[0] * 10^0) = 55350 + 123 * 6 = 56088
这样就不再需要steps
数组(在我的示例中为S
)。
另外,请考虑先在数组中存储最低位数的数字。这允许您用索引转换替换* 10^N
步骤。
A = 123
B = 456
R = 0
R[0:] += A * B[0] = 123 * 6 = 738()
R[1:] += A * B[1] = 123 * 5 + 73 = 688(8)
R[2:] += A * B[2] = 123 * 4 + 68 = 560(88)
()
部分是R
的索引移过的数字。这种技术还可以更容易地添加或删除最重要的数字,因为它们位于数组的末尾而不是开头。
答案 1 :(得分:1)
我注意到的一件事是steps
初始化为x.numDigits - 1
,但你的for循环超过了数组的末尾。也许您的意思是steps
的大小应为x.numDigits
。可能还有其他错误。