您的位置:首页 > 编程语言 > C语言/C++

C++实现大数运算 加法部分。

2017-08-08 19:14 711 查看
由于编程语言提供的基本数值数据类型表示的数值范围有限,不能满足较大规模的高精度数值计算,因此需要利用其他方法实现高精度数值的计算,于是产生了大数运算。大数运算主要有加、减、乘三种方法。

所以我就打算做一个大数运算的项目。

其中每个数字,是动态分配的字符串的形式进行存储和计算的。

下面是每个数的类的组成

class Bigint
{
public:
Bigint() {}
Bigint(const char *);//用字符串创建大数。
Bigint(int);        // 用传入的参数n,创建长度为n的大数,默认为0;
Bigint(Bigint &);
int getlength();
~Bigint();
char *num;
int length;
friend ostream & operator<<(ostream &, Bigint &);
};
运算的核心代码

class Operation
{
public:
Operation(const char *str1, const char *str2);
~Operation();
virtual Bigint& GetResult();
Bigint num1;
Bigint num2;
Bigint result;
char ch;
};

class OperationAdd : public Operation
{
public:
OperationAdd(const char *str1, const char *str2);
virtual Bigint& GetResult();
};
这里 运用了简单的工厂模式,用C++的多态和虚函数,实现了代码的低耦合,方便以后进行修改和增添。

Operation类的实现

Operation::Operation(const char *str1, const char *str2) :num1(str1), num2(str2){}
Operation::~Operation(){}
Bigint& Operation::GetResult()
{
return Bigint("0");
}


这里显式调用了Bigint类的构造函数,而且由于放在{}中,C++编译器会自动认为这是重载()的运算,所以只能用冒号语法,来进行初始化。

OperationAdd类的实现

下面的子类的构造函数是直接调用父类的构造函数,同理,也只能用冒号语法。

OperationAdd::OperationAdd(const char *str1, const char *str2) :Operation(str1, str2) {}
Bigint& OperationAdd::GetResult()
{
int carrynum = 0;
result.num = new char[(result.length = num1.length > num2.length ? num1.length + 1 : num2.length + 1)+1];
int length = result.length - 1;
int temp = 0;
for (int i = num1.length -1, j = num2.length -1; length >= 0;)
{
if(i >= 0 && j >= 0)
{
temp = num1.num[i--] + num2.num[j--] + carrynum - 2 * '0';
result.num[length--] = temp % 10 + '0';
carrynum = temp / 10;
}
else if (i >= 0)
{
temp = num1.num[i--] + carrynum
a5b0
- '0';
result.num[length--] = temp % 10 + '0';
carrynum = temp / 10;
}
else if (j >= 0)
{
temp = num2.num[j--] + carrynum - '0';
result.num[length--] = temp % 10 + '0';
carrynum = temp / 10;
}
else if (carrynum != 0)
{
result.num[length--] = carrynum + '0';
}
else
{
for (int k = 0; k < result.length - 1; k++)
{
result.num[k] = result.num[k + 1];
}
result.length--;
length--;
}
}
result.num[result.length] = '\0';
return result;
}
这个加法的具体实现:

  首先我们的决定结果result的长度,我们可以这样想,两个数相加,有两种可能:1.保持最大数的位数;2.在最大数的位数基础上进了一位;

在这里我取了最大可能的位数。

   加法过程模仿手工过程,个位+个位,满十进位。如果两个都有数的话

temp = num1.num[i--] + num2.num[j--] + carrynum - 2 * '0';
result.num[length--] = temp % 10 + '0';
carrynum = temp / 10;
由于是两个字符的相加,所以需要减去两个‘0’,转到0~9的相加,carrynum是进位数,默认第一次为0,两个数相加,比如5 + 6  

它们的和和10取余就是留在个位的数,它们的和和10相除就是留在十位的数。

假设有一个数num2相加的时候没有数了的时候,实现应该是

temp = num1.num[i--] + carrynum - '0';
result.num[length--] = temp % 10 + '0';
carrynum = temp / 10;
还是应该取一下进位和本数的和,因为有可能9999999 + 1呢!

在两个数都没有位数的时候,而length还没有完的时候

else if (carrynum != 0)
{
result.num[length--] = carrynum + '0';
}
else
{
for (int k = 0; k < result.length - 1; k++)
{
result.num[k] = result.num[k + 1];
}
result.length--;
length--;
}

这个就是看又没有进位,如果有进位,就把第一位即result.num[0] =carrynum + '0';
如果没有进位的话,就集体向前移一位,防止有01513这种情况出现。

这样就实现了大数的运算,部分实现,我没有给出,这个项目还不完善,比如还有其他运算没有实现,比如没有宽展到小数部分,

等我将全部实现后,咱们githup见吧,有什么改进意见可以留言还有对乘法有什么好的实现方式 也可以帮帮博主,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: