[英]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_pos
和bigint::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 * 3
与4 + 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
是一个不适合int
或long
的巨大数字,则我们不能使用“传统” 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.