前言:
随着做题数量的增加,我就慢慢地发现了大整数四则运算的重要性。
但是这些东西挺多的,设计起来也比较复杂,我们不能每次遇到需要大整数四则运算的题,就又重新编写一遍代码吧。
因此,我就想着说把之前刚入门时,苦熬一整天才写出的大整数四则运算代码发上来,供大家,包括我以后方便学习参考。
当然,程序是很久以前写的了,那时候还没学过算法,不懂什么优化,等以后有时间,再优化一下吧。
不过正常计算应该是没什么问题的。
具体代码如下:
#include<iostream>
#include<cstring>
#include<conio.h>
#include<cstdlib>
using namespace std;
const int MAXSIZE = 1000;
//函数声明
void Menu_BigInt();//-------------------------------------大整数四则运算菜单
int In_BigInt(char *a);//---------------------------------大整数的输入
void Sum_BigInt(char *a, char *b, char *sum);//-----------大整数加法运算
void Jian_BigInt(char *a, char *b, char *jian);//---------大整数减法运算
void Cheng_BigInt(char *a, char *b, char *cheng);//-------大整数乘法运算
void Chu_BigInt(char *a, int b, int w, char *chu);//------大整数除法运算
int Strcmp_BigInt(char *s1, char *s2);//------------------比较两个大整数的大小
void Clean_BigInt(char *a)
{ /*清除非数字字符和前面的0干扰*/
int i, j;
for(i = 0; a[i] < '0' || a[i] > '9' || a[i] == '0' && a[i+1] != '\0'; i++); //判断是否有干扰项
for(j = i; j < strlen(a) && i; j++)
{ /*将干扰项覆盖*/
a[j-i] = a[j];
}
if(j) a[j-i] = '\0'; //上锁
if(a[0] == '\0')
{ /*大整数最少为0*/
a[0] = '0';
a[1] = '\0';
}
}
int Strcmp_BigInt(char *s1, char *s2)
{ /*比较两个大整数的大小,s1大于s2返回1,等于返回0,小于返回-1*/
int len1 = strlen(s1), len2 = strlen(s2);
int flag1 = 0, flag2 = 0;
int i = 0;
if(len1 > len2) return 1;
if(len1 == len2)
{
while(i < len1)
{
if(s1[i] == s2[i])
{ /*相等继续往下判断*/
i++;
}
else if(s1[i] > s2[i])
{ /*s1大于s2,flag1标记1,跳出循环*/
flag1 = 1;
break;
}
else
{ /*s1小于s2,flag2标记1,跳出循环*/
flag2 = 1;
break;
}
}
if(flag1) return 1;
if(flag2) return -1;
if(i == len1) return 0;
}
if(len1 < len2) return -1;
}
int In_BigInt(char *a)
{ /*大整数的输入,成功返回1,失败返回0*/
int i;
cout << "请输入大整数:";
cin >> a;
Clean_BigInt(a);
//检错
for(i = 0; i < strlen(a); i++)
{
if(a[i] < '0' || a[i] > '9')
{
cout << "大整数输入有误!" << endl;
return 0;
}
}
return 1;
}
void Sum_BigInt(char *a, char *b, char *sum)
{ /*大整数加法运算,a和b输入,sum输出*/
char c[MAXSIZE+1]; //开辟一个1001大小的字符串空间
int i = strlen(a) - 1; //i为字符串a的实际长度-1
int j = strlen(b) - 1; //j为字符串b的实际长度-1
int num; //num为两数相加结果的个位数
int jin = 0; //jin为进位数,初始化为0
int wei = 0; //wei为当前运算位数,初始化为0
int flag = 1; //最后结果高位为0时标记1,遇到第一个非0时标记0
Clean_BigInt(a), Clean_BigInt(b);
while(i >= 0 && j >= 0)
{ /*如果两数在该位都有值*/
num = a[i]-'0' + b[j]-'0' + jin; //求和
if(num > 9)
{ /*判断是否进位并进行数据处理*/
jin = num / 10;
num = num % 10;
}
else jin = 0;
c[wei++] = num + '0'; //将本位数转换为相应字符赋值给c
i--, j--;
}
while(i >= 0)
{ /*如果a有剩余*/
num = a[i]-'0' + jin; //此位b无值,只考虑进位数值
if(num > 9)
{ /*判断是否进位并进行数据处理*/
jin = num / 10;
num = num % 10;
}
else jin = 0;
c[wei++] = num + '0'; //将本位数转换为相应字符赋值给c
i--;
}
while(j >= 0)
{ /*如果b有剩余*/
num = b[j]-'0' + jin; //此位a无值,只考虑进位数值
if(num > 9)
{ /*判断是否进位并进行数据处理*/
jin = num / 10;
num = num % 10;
}
else jin = 0;
c[wei++] = num + '0'; //将本位数转换为相应字符赋值给c
j--;
}
//如果a和b都没有剩余,但上一次求和的结果存在进位值
if(jin != 0) c[wei++] = jin + '0';
for(i = wei - 1, j = 0; i >= 0; i--)
{ /*逆置输入到sum中*/
if(flag && c[i] == '0')
{ /*去掉高位的0*/
continue;
}
else
{
flag = 0;
sum[j++] = c[i];
}
}
sum[j] = '\0'; //给字符串sum上锁
}
void Jian_BigInt(char *a, char *b, char *jian)
{ /*大整数减法运算,a和b输入,jian输出*/
char c[MAXSIZE]; //开辟一个1000大小的字符串空间
int len1 = strlen(a) - 1; //len1为字符串a的实际长度-1
int len2 = strlen(b) - 1; //len2为字符串b的实际长度-1
int num; //num为两数相减结果的个位数
int jie = 0; //jie为借位数,初始化为0
int wei = 0; //wei为当前运算位数,初始化为0
int flag = 1; //高位为0标记1,遇到第一个非0的数标记0
int i, j;
Clean_BigInt(a), Clean_BigInt(b);;
if(Strcmp_BigInt(a, b) > 0)
{ /*如果a大于b,结果为正的a-b*/
i = len1, j = len2; //初始化i为len1,j为len2
while(j >= 0)
{ /*如果小的数b在该位有值,即两数在该位都有值*/
a[i] = a[i] - jie; //减去上一位的借位
num = (a[i]-'0') - (b[j]-'0'); //求差
if(num < 0)
{ /*判断是否需要借位并进行数据处理*/
jie = 1;
num += 10;
}
else jie = 0;
c[wei++] = num + '0'; //将本位数转换为相应字符赋值给c
i--, j--;
}
while(i >= 0)
{ /*如果a有剩余*/
a[i] = a[i] - jie; //减去上一位的借位
num = a[i] - '0'; //此位b无值,只考虑借位数值
if(num < 0)
{ /*判断是否需要借位并进行数据处理*/
jie = 1;
num += 10;
}
else jie = 0;
c[wei++] = num + '0'; //将本位数转换为相应字符赋值给c
i--;
}
for(i = wei - 1, j = 0; i >= 0; i--)
{ /*逆置输入到sum中,结果为正数*/
if(flag && c[i] == '0')
{ /*去掉高位的0*/
continue;
}
else
{
flag = 0;
jian[j++] = c[i];
}
}
jian[j] = '\0'; //给字符串sum上锁
}
else if(!Strcmp_BigInt(a, b))
{ /*如果a和b相等,差为0*/
jian[0] = '0';
jian[1] = '\0';
}
else
{ /*如果a小于b,结果为负的b-a*/
jian[0] = '-'; //的数首位存负号
Jian_BigInt(b, a, jian+1); //的数运算位指针后移为jian+1
}
}
void Cheng_BigInt(char *a, char *b, char *cheng)
{ /*大整数乘法运算:a和b输入,cheng输出*/
char c[MAXSIZE*2]; //开辟一个2000大小的字符串空间
int wei, num; //wei为当前运算位,num是当前位的值
int len1 = strlen(a) - 1, len2 = strlen(b) - 1; //len1是a的长度-1,len2是b的长度-1
int len = len1 + len2 + 2; //最后总长度
int i, j, flag = 1; //i, j为循环介质,flag同上
Clean_BigInt(a), Clean_BigInt(b);
for(i = 0; i < len; i++)
{ /*初始化让全部有效位清0,方便后续进位操作*/
c[i] = '0';
}
for(i = 0; i <= len1; i++)
{ /*遍历字符串a*/
for(j = 0; j <= len2; j++)
{ /*遍历字符串b*/
wei = len - 2 - (i + j); //初始化当前位
num = (c[wei]-'0') + (a[i]-'0') * (b[j]-'0'); //计算当前位的值
while(1)
{ /*循环判断是否进位*/
if(num > 9)
{ /*如果需要进位,进位并循环判断下一位是否进位*/
c[wei] = num % 10 + '0'; //当前位结果
num = (c[++wei]-'0') + (num / 10); //进位结果
}
else
{ /*如果不需进位,直接赋值并跳出循环*/
c[wei] = num + '0';
break;
}
}
}
}
for(i = 0, j = len - 1; j >= 0; j--)
{ /*将c逆置输出给cheng*/
if(flag && c[j] == '0')
{ /*去掉高位的0*/
continue;
}
else
{
flag = 0;
cheng[i++] = c[j];
}
}
cheng[i] = '\0'; //上锁
}
void Chu_BigInt(char *a, char *b, int w, char *chu)
{ /*大整数除法运算:a,b输入,chu输出,w为小数位数*/
char t[MAXSIZE] = "", p[MAXSIZE] = ""; //b为除数,p为临时字符串
int j = 0;
int wei = 0;
int i;
int num;
int len, len1, len2;
Clean_BigInt(a), Clean_BigInt(b);
while(Strcmp_BigInt(t, b) < 0)
{ /*找出商的最高位对应a中的位置*/
t[j] = a[j];
j++;
t[j] = '\0'; //上锁
}
num = 0, strcpy(p, t);
while(Strcmp_BigInt(p, b) >= 0)
{ /*num = t / b*/
Jian_BigInt(p, b, p);
num++;
}
chu[wei++] = num + '0';
while(Strcmp_BigInt(t, b) >= 0)
{ /*t = t % b*/
Jian_BigInt(t, b, t);
}
for(i = j; i < strlen(a); i++)
{ /*整数部分*/
len = strlen(t);
t[len] = a[i], t[len+1] = '\0';
Clean_BigInt(t);
if(Strcmp_BigInt(t, b) < 0)
{
chu[wei++] = '0';
continue;
}
//c[wei++] = t / b +'0'
num = 0, strcpy(p, t);
while(Strcmp_BigInt(p, b) >= 0)
{ /*num = t / b*/
Jian_BigInt(p, b, p);
num++;
}
chu[wei++] = num + '0';
while(Strcmp_BigInt(t, b) >= 0)
{ /*t = t % b*/
Jian_BigInt(t, b, t);
}
}
chu[wei++] = '.';
for(i = 0; i < w; i++)
{ /*小数部分*/
len = strlen(t);
t[len] = '0', t[len+1] = '\0'; //t = t*10
Clean_BigInt(t);
if(Strcmp_BigInt(t, b) < 0)
{
chu[wei++] = '0';
continue;
}
//c[wei++] = t / b +'0'
num = 0, strcpy(p, t);
while(Strcmp_BigInt(p, b) >= 0)
{ /*num = t / b*/
Jian_BigInt(p, b, p);
num++;
}
chu[wei++] = num + '0';
while(Strcmp_BigInt(t, b) >= 0)
{ /*t = t % b*/
Jian_BigInt(t, b, t);
}
}
chu[wei] = '\0'; //上锁
}
void Menu_BigInt()
{ /*大整数四则运算菜单*/
char a[MAXSIZE], b[MAXSIZE];
int i;
cout << "欢迎使用龙少大整数四则运算器:" << endl << endl;
cout << "1.加法运算" << endl;
cout << "2.减法运算" << endl;
cout << "3.乘法运算" << endl;
cout << "4.除法运算" << endl;
cout << "*.按任意键退出" << endl << endl;
cout << "帅气的龙少提示您:不要乱敲无用的空格与回车,出错后果自负!" << endl << endl;
cout << "请选择:";
cin >> i;
fflush(stdin); //清空输入缓冲区
switch(i)
{
case 1: /*加法运算*/
if(In_BigInt(a) && In_BigInt(b))
{
char sum[MAXSIZE+1];
Sum_BigInt(a, b, sum);
cout << "和为:" << sum << endl;
}
break;
case 2: /*减法运算*/
if(In_BigInt(a) && In_BigInt(b))
{
char jian[MAXSIZE];
Jian_BigInt(a, b, jian);
cout << "差为:" << jian << endl;
}
break;
case 3: /*乘法运算*/
if(In_BigInt(a) && In_BigInt(b))
{
char cheng[MAXSIZE*2];
Cheng_BigInt(a, b, cheng);
cout << "积为:" << cheng << endl;
}
break;
case 4: /*除法运算*/
if(In_BigInt(a) && In_BigInt(b))
{
char chu[MAXSIZE];
int w;
cout << "请输入小数位数:";
cin >> w;
Chu_BigInt(a, b, w, chu);
cout << "商为:" << chu << endl;
}
break;
default:
cout << "选择输入有误!" << endl;
break;
}
cout << endl;
}
int main()
{
Menu_BigInt();
system("pause");
return 0;
}