在数组C ++中乘以大字符串

时间:2015-04-24 16:09:48

标签: c++ arrays string class bigint

在这里,我有一个SafeArray(不是那么安全,但我的老师说这很好)课程和一个bigint课程。我的bigint类可以添加和减去很好但是当我尝试乘法函数它根本不打印任何东西时,我已经尝试调试并单步执行它但我似乎无法弄明白,一直在努力一段时间,我绝望地陷入困境。任何帮助,将不胜感激。感谢

        #include <iostream>
        using namespace std;
#include <algorithm>

template<typename Element>
class SafeArray
{
    int size;
    Element*Array;
    Element def;

public:
    SafeArray()                         //default constructor(with no parameter)
    {
        size = 10;
        Array = new Element[size]();
    }

    SafeArray(int value)         //constructor with one int
    {
        size = value;
        Array = new Element[value];
        for (int i = 0; i < size; ++i)
            Array[i] = 0;
    }

    ~SafeArray() {
        delete[] Array;
    }                                       //destructor

    SafeArray(const SafeArray& rhs) : size(rhs.size), Array(new Element[size]), def(rhs.def)
    {
        for (int i = 0; i < size; ++i )
            Array[i] = rhs.Array[i];
    }

    SafeArray& operator=(SafeArray rhs)
    {
        std::swap(Array, rhs.Array);
        std::swap(size, rhs.size);
        std::swap(def, rhs.def);
        return *this;
    }

    Element get(int pos)    const                 //get method
    {
        if (pos<0)
        {
            cout << "error";
        }

        return Array[pos];
    }

    void set(int pos, Element val)
    {
        if (pos<0)
        {
            cout << "error";
            return;
        }
        if (pos >= size)
        {
            resize(pos + 1);
        }
        Array[pos] = val;
    }

    void resize(int new_size)
    {
        Element*temp = new Element[new_size];
        for (int i = 0; i<size; i++)
        {
            temp[i] = Array[i];
        }
        delete[]Array;
        Array = temp;
        size = new_size;
    }

    void set_default(Element d)        //set_default
    {
        def = d;
    }

    int get_size()                       //get size
    {
        return size;
    }
};

int size = 100; //for testing

class bigint
{
    SafeArray<int> *arr;
public:
    bool sign;
bigint()                                                   //initializes to zero
    {
        arr = new SafeArray<int>;
        for(int i =0;i < size; i++)
            arr->set(i,0);
    }

void print()                                               //prints numbers without zeroes in front
    {
        bool start_num=false;
        for(int i = 0;i <arr->get_size() ;i++)
        {
            if(arr->get(i)!=0 && start_num==false )
            {start_num=true;
                cout << arr->get(i);}
         else if(start_num==true)
             cout<<arr->get(i);

        }

       cout<<endl;
    }
    void assign(const bigint &A)                             //
{
    for(int i=0;i<arr->get_size();i++)
    {                                                            //Ways to initialize stuff
        arr->set(i,A.arr->get(i));
    }

}
void assign(string num)                                  
    {
        long len = num.length();
        int j=arr->get_size()-1;
        for(long i=len-1;i>=0;i--)
        {
            arr->set(j,num[i]-48);
            j--;
        }
    }
void add_pos(const bigint &A)                                //add big ints
    {
        int carry=0;
        for(int i=size-1;i>=0;i--)
           {
               int result = arr->get(i)+A.arr->get(i)+carry;
               arr->set(i,result%10);
               carry=result/10;
           }
    }

void sub_pos(const bigint &A)
        {
           int borrow=0;
           for(int i=size-1;i>=0;i--)
           {
              int result = ((arr->get(i) - A.arr->get(i)-borrow));
              if(result<0)
              {
                 arr->set(i,result +10);
                 borrow = 1;
              }
              else
              {
                 arr->set(i,result);
                 borrow = 0;
              }
            }
        }


    void multiply(const bigint &A)
        {
            for(int i=size-1;i>=0;i--)
                {
                  int carry=0;

               for(int j=size-1;j>=0;j--)
                 {
                   int product=((arr->get(i)*A.arr->get(j))+carry);
                   arr->set(i+j,product%10);
                   carry=product/10;
                 }
            }
    }

    }

int main()
{
 bigint a,b;
a.assign("1234");
b.assign("5678");
a.multiply(b);
a.print();

return 0;
}

1 个答案:

答案 0 :(得分:0)

鉴于对SafeArray

的评论和以下更改

http://coliru.stacked-crooked.com/a/0f22a24e04421ae1

实现乘法的一种方法是利用你已经说过的函数,即bigint::add_posbigint::sub_pos来进行乘法运算。目标是通过将m * n添加到自身m次来模拟n-1。例如,4 * 34 + 4 + 4相同(我们为自己添加了4次)。

注意:如果要求您必须完全独立于现有功能编写乘法代码,和/或使用SafeArray的不安全版本,那么这个答案不会帮助您和您必须从头做事。

<强>预赛:

应该做的第一件事是将SafeArray类中bigint的指针替换为实际的实例:

SafeArray<int> arr;

第二项更改将是arr->课程中arr.更改为bigint。这应该是无缝变化。

现在,要做的第三件事是在bigint中创建一个辅助函数,调用它is_zero来确定bigint是否代表0.你可以通过编写一个来轻松完成循环并确保arr中的所有条目都为0。该函数应为const,即

bool is_zero() const;

最后一项更改是您的bigint默认构造函数中存在错误。该错误是您没有初始化arr SafeArray以拥有size个元素。您使用了默认值,即10。要解决此问题,请将arr初始化为size元素

bigint() : arr(size)
{
    for (int i = 0; i < size; i++)
        arr.set(i, 0);
}

我保留了您的全局变量size,但它确实应该从全局变量中删除,并且您的bigint类应该使用arr.get_size()来获取数组的大小。

<强>实施

现在我们使用您现有的函数来实现multiply。它是一种迂回的方式,对于非常大的值可能会很慢。

让我们来看看代码:

void multiply(const bigint &A)
{
    // check for multiplication by 0
    if ( A.is_zero() )
    {
       *this = A;  // copy our paramter (which is 0) to this object
       return;  
    }

    bigint tempInt(*this);  // our original value
    bigint startVal(*this);  // our running total
    bigint startA(A);   // our counter
    bigint subtractor;
    subtractor.assign("1");  // our decrementor for looping

    // subtract one from the number of times we need to add
    startA.sub_pos(subtractor);

    // keep adding until the number of times we've added is 
    // sufficient
    while (!startA.is_zero()) 
    {
        // add to running total
        startVal.add_pos(tempInt);

        // subtract 1 from our counter
        startA.sub_pos(subtractor);
    } 

    // assign the final result to our object, and we're done
    *this = startVal;
}

那我们做了什么?

首先我们检查了0的乘法。如果是,那么我们将所有内容归零并返回。

如果不是0的乘法,我们设置一个临时bigint,它保存我们的原始值(tempInt)。然后我们设置另一个bigint来保存我们当前的&#34;运行总数&#34; (startVal)。我们设置了另一个bigint,它将保持乘数startA。请注意我们如何使用复制构造函数从现有构造函数构造临时bigint。如果您的SafeArray没有真正安全(即您坚持使用原始实现),则无法做到这一点。

现在,当我们需要计算添加的次数时,就会出现问题。为此,我们设置了第四个名为bigint subtractor的{​​{1}},其所做的就是将自己初始化为1。我们需要这个来帮助我们从bigint乘数中减去1(这是bigint::sub_pos在我们的设计中发挥作用的地方)。

请注意,我们必须完成所有这些操作以减去1,而不是使用简单的int&#39; s。原因 - 如果传递给bigint的{​​{1}}是一个巨大的数字,不适合intlong,那么我们就无法使用&#34;传统&#34; C ++整数类型。我们正在处理100位数字,并且可能没有C ++编译器具有本机100位整数类型。

所以我们从乘数中减去1开始。如果乘数现在为零,我们就不会循环(基本上这会将乘法乘以1的情况,但请参阅下面的进一步编辑,以获得乘以1的优化方法。)

如果乘数大于0,我们现在所做的就是在我们的运行总数上调用add_pos,直到我们的乘数变为0.我们通过测试我们的乘数来看看它是否已经达到0,通过调用{每次is_zero条件{1}}。每次我们调用while()从乘数中减去1。

从高级别的角度看待这个乘法函数正在做什么 - 在纸面上进行研究 - 你应该知道正在做什么(偷偷地避免实际编写乘法代码,就像你在你的问题)。

最后,我们将运行总计分配给 this 。就是这样。全部使用您现有的功能,再加上一个简单的助手,让您的sub_pos课程更安全一些。

编辑: 您可以进行的优化是检查乘法乘以1.您这样做的方法是设置计数器,从中减去1,并检查计数器是否为0.如果为0,则返回而不进行任何进一步的工作