似乎无法繁殖困难的方式

时间:2011-11-15 02:50:47

标签: c++ dynamic

我正在尝试使用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';
}

2 个答案:

答案 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。可能还有其他错误。