简体   繁体   English

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

[英]Multiply Large Strings in Array C++

Here I've got a SafeArray(not that safe but my teacher said it's fine) class and a bigint class. 在这里,我有一个SafeArray(不是很安全,但是我的老师说没问题)类和bigint类。 My bigint class can add and subtract just fine but when I try the multiply function it doesn't print anything at all, i've tried debugging and stepping through it but I can't seem to figure it out, been working on it for a while and am hopelessly stuck. 我的bigint类可以加减法,但是当我尝试乘法函数时,它根本不显示任何内容,我尝试调试并逐步执行它,但似乎无法弄清楚,为此我一直在努力一段时间,无可救药地被困住了。 Any help would be appreciated. 任何帮助,将不胜感激。 Thanks 谢谢

        #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;
}

Given the comments and the following changes to SafeArray 给定注释以及对SafeArray的以下更改

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

one way to achieve multiplication is to leverage the functions you say already work, namely bigint::add_pos and bigint::sub_pos to do the multiplication. 一种实现乘法的方法是利用您已经说过的功能,即bigint::add_posbigint::sub_pos进行乘法。 The goal is to simulate m * n by adding m to itself n-1 times. 目的是通过将m加到自身n-1次来模拟m * n For example, 4 * 3 is the same as 4 + 4 + 4 (we added 4 to itself 2 times). 例如, 4 * 34 + 4 + 4 (我们将4自身加2倍)。

Note: If the requirements are that you have to write the multiply code totally independent of the existing functions, and/or use the unsafe version of SafeArray , then this answer won't help you and you will have to do things from scratch. 注意:如果要求您必须完全独立于现有功能编写乘法代码,和/或使用SafeArray的不安全版本,则此答案将无济于事,您将不得不从头做起。


Preliminaries: 初步资料:

The first thing that should be done is to replace the pointer to the SafeArray in your bigint class to an actual instance: 首先要做的是将bigint类中指向SafeArray的指针替换为实际实例:

SafeArray<int> arr;

The second changes will be the changing of arr-> to arr. 第二个更改是将arr->更改为arr. within your bigint class. 在您的bigint类中。 This should be seamless change. 这应该是无缝的更改。

Now, the third thing to do is to create a helper function in bigint , call it is_zero to determine if the bigint represents 0. You can easily do this by writing a loop and making sure that all entries in arr are 0 . 现在,要做的第三件事是在bigint创建一个辅助函数,将其is_zero以确定bigint表示0。您可以通过编写循环并确保arr中的所有条目均为0来轻松地做到这一点。 The function should be const , ie 该函数应为const ,即

bool is_zero() const;

The last change is that you have a bug in your bigint default constructor. 最后的更改是,您的bigint默认构造函数中存在一个错误。 That bug is that you didn't initialize the arr SafeArray to have size elements. 该错误是您没有将arr SafeArray初始化为具有size元素。 You used the default, which is only 10. To fix this, initialize the arr to size elements 您使用的默认值仅为10。要解决此问题,请将arr初始化为size元素

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

I kept your global variable size , but it really should be removed from being a global, and your bigint class should use arr.get_size() to get the size of the array. 我保留了全局变量size ,但实际上应该将其从全局变量中删除,并且bigint类应使用arr.get_size()来获取数组的大小。


Implementation: 实现方式:

So now we get to the implementation of multiply using your existing functions. 因此,现在我们开始使用您现有的函数来实现multiply It is kind of a roundabout way, and it may be slow for very large values. 这是一种回旋方式,对于很大的值可能会很慢。

Let's get to the code: 让我们看一下代码:

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;
}

So what did we do? 那我们做了什么?

First we checked for multiplication of 0. If so, then we zero out everything and just return. 首先,我们检查乘数是否为0。如果是,则将所有内容归零,然后返回。

If not a multiplication of 0, we set up a temporary bigint that holds our original value (tempInt). 如果不是0的乘积,我们将设置一个临时bigint来保存我们的原始值(tempInt)。 Then we setup another bigint that holds our current "running total" ( startVal ). 然后,我们设置另一个bigint来保存当前的“运行总计”( startVal )。 We set up another bigint that will hold our multiplier startA . 我们设置了另一个bigint来保存乘数startA Note how we use the copy constructor to construct temporary bigint 's from existing ones. 请注意,我们如何使用复制构造函数从现有的构造器构造临时的bigint This would not be possible if your SafeArray wasn't made truly safe (ie you stuck with your original implementation instead). 如果您的SafeArray并非真正安全(例如,您坚持使用原始实现),那将是不可能的。

Now, the trouble happens when we need to keep a count of the number of times we add. 现在,当我们需要统计添加次数时,就会发生麻烦。 To do that, a fourth bigint called subtractor was set up, and all it does is initialize itself to 1 . 为此,设置了第四个bigint称为subtractor器,它所做的就是将自身初始化为1 We need this to help us subtract 1 from our bigint multiplier (this is where bigint::sub_pos comes into play in our design). 我们需要它来帮助我们从bigint乘数中减去1(这就是bigint::sub_pos在我们的设计中起作用的地方)。

Note that we had to do all of this to subtract 1, and not use simple int 's. 请注意,我们必须将所有这些都减去1,而不要使用简单的int The reason -- if the bigint that is passed to multiply is a huge number that won't fit into an int or long , then we can't use the "traditional" C++ integer types. 原因是-如果传递给乘法的bigint是一个不适合intlong的巨大数字,则我们不能使用“传统” C ++整数类型。 We are dealing with 100 digit numbers and there is probably no C++ compiler that has native 100 digit integer types. 我们正在处理100位数字,并且可能没有C ++编译器具有本地100位整数类型。

So we start out by subtracting 1 from our multiplier. 因此,我们从乘数减去1开始。 If the multiplier is now zero, we just don't loop (essentially this takes care of the multiplication by 1 case, but see the further edit below for an optimized way to accomplish multiplication by 1). 如果乘数现在为零,我们就不循环(本质上这是乘以1的情况,但是请参见下面的进一步编辑以获取乘以1的优化方法)。

If the multiplier is greater than 0, all we do now is call add_pos on our running total until our multiplier goes to 0. We do that by testing our multiplier to see if it has reached 0 by calling is_zero each time for the while() condition. 如果乘数大于0,那么我们现在要做的就是在运行的总计上调用add_pos ,直到乘数变为0。我们通过测试乘数以查看是否达到0来实现这一点, is_zero每次while()都调用is_zero条件。 Each time we call sub_pos to subtract 1 from the multiplier. 每次我们调用sub_pos从乘数中减去1。

Work it out on paper in terms of a high-level look at what this multiply function is doing -- you should get the idea of what is being done (sneakily avoiding having to actually write the multiplication code as you did in your question). 从更高层次上看一下乘法函数的工作原理,在纸上解决问题-您应该了解正在做的事情(偷偷地避免像您在问题中那样实际上编写乘法代码)。

At the end, we assign our running total to this . 最后,我们将运行总计分配给this That's it. 而已。 All using your existing functions, plus an addition of a simple helper, and making your SafeArray class a little safer. 所有这些都将使用您现有的功能,再加上一个简单的帮助程序,并使您的SafeArray类更加安全。

Edit: An optimization you can make is to check for multiplication by 1. The way you do that is to set up the counter, subtract 1 from it, and check if the counter is 0. If it is 0, then return without doing any further work. 编辑:您可以进行的优化是检查是否乘以1。您的方法是设置计数器,从中减去1,然后检查计数器是否为0。如果为0,则不做任何操作就返回进一步的工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM