小鱼儿大数运算(前段时间写的 加减乘除)
因为最近论坛交流的气氛太那个,所以贴这个我发到自己空间的文章。其实不怎么想发的,因为这个代码没有怎么注释,又看到我刚刚的发的那篇补码的文章。觉得用我这种方法现的没有太多技术含量,
大数运算主要是用到数组
加减用到是竖式运算。
除法是转换为减法。。
以后再修改代码加上注释。。
效率没有很科学的测试,但速度人来测试还是蛮快的
big.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#define MAX_BIG 200
using namespace std;
typedef struct tagBig
{
char num[MAX_BIG];
int flag; //flag > 0 代表正数 反之为
}Big;
void Init(char *n,int flag,Big* n1);
void ReStr(char* str1,char* str2);
void Add(Big n1,Big n2,Big *Result);
void Sub(Big n1,Big n2,Big * Result);
void Mul(Big n1,Big n2,Big * ReSult);
void Dul(Big n1,Big n2,Big * ReSult);
void Mod(Big n1,Big n2,Big * ReSult);
int CompareBig(Big n1,Big n2); //比较2个数的大小 返回一 则为大于 反之小于
void PrinBig(Big *n); //输去大数字
void DelZero(char* str); //除掉多余的0
void DelLastSero(char* str); //除掉最后一个0
big.cpp
#include "big.h"
void DelZero(char* str)
{
int len = strlen(str);
if(NULL == str || 0 == len)
{
return;
}
for(int i = len -1 ; i >= 0; i--)
{
if(str[i]=='0')
{
str[i] = '\0';
}
else
{
break;
}
}
}
void DelLastSero(char* str)
{
int len = strlen(str) - 1;
if('0' == str[len])
{
str[len] = '\0';
}
}
void PrinBig(Big *n)
{
if(n!=NULL)
{
if(n->flag ==1)
{
puts(n->num);
}
else
{
//puts("....");
printf("-%s",n->num);
}
}
}
int CompareBig(Big n1,Big n2)
{
if(n1.flag ==1 && n2.flag == 0)
{
return 1;
}
if(n1.flag == 0 && n2.flag == 1)
{
return 0;
}
//当2个数的符号是一样的时候
//当符号都为整数的时候
if(n1.flag == 1)
{
if(strlen(n1.num)>strlen(n2.num))
{
return 1;
}
else
if(strlen(n1.num)<strlen(n2.num))
{
return 0;
}
else
{
for(int i = 0; i< strlen(n1.num); i++)
{
if(n1.num[i]>n2.num[i])
{
return 1;
}
else
if(n1.num[i]<n2.num[i])
{
return 0;
}
}
return -1; //这里是2个数字相等于的时候
}
}
else
if(n1.flag == 0)
{
if(strlen(n1.num)>strlen(n2.num))
{
return 0;
}
else
if(strlen(n1.num)<strlen(n2.num))
{
return 1;
}
else
{
for(int i = 0; i< strlen(n1.num); i++)
{
if(n1.num[i]>n2.num[i])
{
return 0;
}
else
if(n1.num[i]<n2.num[i])
{
return 1;
}
}
return -1; //这里是2个数字相等于的时候
}
}
return 1; //其实这个没有什么用 但编译器有一个警告 我就加了这个
}
void Init(char *n,int flag,Big* n1)
{
strcpy(n1->num,n);
n1->flag = flag;
}
void ReStr(char* str1,char* str2)
{
int n =0;
for(int i = strlen(str1)-1; i >=0; i--)
{
str2[n++] = str1[i];
}
str2[n] = '\0';
}
void Add(Big n1,Big n2,Big *Result)
{
int len1 = strlen(n1.num)-1;
int len2 = strlen(n2.num)-1;
int jw = 0; //进位大小
int l,k,re;
char r1[MAX_BIG];
char r2[MAX_BIG];
char r3[MAX_BIG]; //申明一个保存结果的数组 但长度也是有限的
int len = len1>len2?len1:len2;
if(strcmp(n1.num,"0") == 0)
{
*Result = n2;
return;
}
if(strcmp(n2.num,"0") == 0)
{
*Result = n1;
return;
}
strcpy(r1,n1.num);
strcpy(r2,n2.num);
if(n1.flag==n2.flag)//同为相同符号
{
//puts("同为正数处理");
for(int i = 0; i <= len; i++)
{
l = r1[len1]-48;
k = r2[len2]-48;
if(i > strlen(n1.num)-1)
l =0;
if(i > strlen(n2.num)-1)
k =0;
re = l + k + jw;
if(re >= 10)
{
re = re%10;
jw = 1;
}
else
{
jw = 0;
}
r3[i] = re + 48;
len1--;
len2--;
}
if(jw)
{
r3[i] = '1';
r3[i+1] = '\0';
}
else
{
r3[i] = '\0';
}
char s[MAX_BIG];
// puts("怎么了啊");
// puts(r3);
// DelZero(r3);
// puts(r3);
//
// puts("是这里吗");
// getchar();
ReStr(r3,s);
Result->flag = n1.flag;
strcpy(Result->num,s);
}
else
{
//进行减号运算
//因为肯定是不同的符号
//把他们变成正数来进行比较
//因为减法在要大数减小数的时候好进行运算
//否者要考虑别的特殊情况。
//所以我们判断他们的数字大小是很重要的
Big b;
if(n1.flag == 0)
{
b.flag = 1;
strcpy(b.num,n1.num);
Sub(b,n2,Result);
if(CompareBig(b,n2)==1)
{
Result->flag = 0;
}
else
{
Result->flag = 1;
}
}
else
{
b.flag = 1;
strcpy(b.num,n2.num);
Sub(n1,b,Result);
if(CompareBig(n1,b))
{
Result->flag = 1;
}
else
{
Result->flag = 0;
}
}
}
}
void Sub(Big n1,Big n2,Big * Result)
{
char str1[MAX_BIG];
char str2[MAX_BIG];
char str3[MAX_BIG];
int jw = 0;
int flag; //存放第二个数字减的时候的符号
if(n2.flag)
{
flag = 0 ;
}
else
{
flag = 1;
}
int l,k,re;
strcpy(str1,n1.num);
strcpy(str2,n2.num);
int len1 = strlen(str1)-1;
int len2 = strlen(str2)-1;
int len = len1>len2?len1:len2;
if(CompareBig(n1,n2) == -1)
{
//puts("不是在这里吗");
Result->flag = 1;
strcpy(Result->num,"0");
return;
}
if(flag == n1.flag)
{
n1.flag = 1;
n2.flag = 1;
Add(n1,n2,Result);
Result->flag = flag;
return;
}
else
{
for(int i = 0; i <= len ; i++)
{
l = str1[len1] -48;
k = str2[len2] - 48;
if(i > strlen(n1.num)-1)
{
l = 0;
}
if(i > strlen(n2.num)-1)
{
k = 0;
}
if(CompareBig(n1,n2) == 1)
{
re = l - k - jw;
}
else
{
re = k - l - jw;
}
//printf("l %d k %d\n re %d",l,k,re);
//getchar();
if(re<0)
{
re += 10;
jw = 1;
}
else
{
jw = 0;
}
str3[i] = re + 48;//把结果转换成字符输入到str3数组中
len1--;
len2--;
}
str3[i] = '\0';
}
char s[MAX_BIG];
DelZero(str3);
ReStr(str3,s);
strcpy(Result->num,s);
//相等于在上面已经处理了
if(CompareBig(n1,n2) == 1)
{
Result->flag = 1;
}
else
{
Result->flag = 0;
}
}
void Mul(Big n1,Big n2,Big * ReSult)
{
char str1[MAX_BIG];
char str2[MAX_BIG];
//char str3[MAX_BIG];//存放结果
char temp[MAX_BIG];
Big *date;
memset(temp,0,sizeof(temp));
int l,k,re; //存放数字的
int jw = 0;
int n = 0,m = 0;
Big t1,t2;
t1.flag = 1;
t2.flag = 1;
strcpy(t1.num,n1.num);
strcpy(t2.num,n2.num);
if(CompareBig(n1,n2))
{
strcpy(str1,n1.num);
strcpy(str2,n2.num);
}
else
{
strcpy(str1,n2.num);
strcpy(str2,n1.num);
}
//把长度的长的放在上面 跟数学里面的竖式运算是一样的
int len1 = strlen(str1)-1;
int len2 = strlen(str2)-1;
date = (Big*)malloc(sizeof(Big)*(strlen(str2))); //分配内存 来存取每个乘后的结果
//int len = len1>len2?len1:len2;
for(int j = len2; j >= 0; j--)
{
l = str2[j] - 48; //l 放竖式下面的
for(int i = len1; i >= 0; i--)
{
k = str1[i] - 48; //k放上面的竖式的
re = k*l+jw;
if(re >=10)
{
jw = re/10;
re = re%10;
}
else
{
jw = 0;
}
temp[m++] = re + 48;//保存转换为字符的单个结果
}
if(0 == jw)
{
temp
­ = '\0';
}
else
{
temp
­ = jw + 48;
temp[m+1] ='\0';
}
m = 0;
char s[MAX_BIG];
ReStr(temp,s);
for(int kk = 0; kk <(len2 - j); kk++)
{
strcat(s,"0");
}
strcpy(date[n].num,s);
//puts(s);
memset(temp,0,sizeof(temp));
date[n].flag = 1; //正负没有关系
n++;
}
Big b;
// for(int kk =0; kk <strlen(str2); kk++)
// {
// printf("%s\n",date[kk].num);
// }
b.flag = 1;
strcpy(b.num,"0");
ReSult->flag = 1;
for(int i = 0; i <=len2; i++)
{
Add(b,date[i],ReSult);
b = *ReSult;
}
if(n1.flag == n2.flag)
{
ReSult->flag = 1;
}
else
{
ReSult->flag = 0;
}
if(strcmp(ReSult->num,"0") == 0)
{
ReSult->flag = 1;
}
free(date);
}
//对0处理减号 除号都要进行处理,现在还没有处理啊
void Dul(Big n1,Big n2,Big * ReSult)
{
char str1[MAX_BIG];
char str2[MAX_BIG];
char str3[MAX_BIG];
memset(str2,0,sizeof(str2));
memset(str3,0,sizeof(str3));
int flag;
if(n1.flag == n2.flag)
{
flag = 1;
}
else
{
flag = 0;
}
n1.flag = 1;
n2.flag = 1;
strcpy(str1,n1.num);
strcpy(str2,n2.num);
//int l,k,re; //存放数字
if(strcmp(n2.num,"0") == 0)
{
puts("除数不能为0");
exit(3);
}
if(CompareBig(n1,n2) == 0)//小于
{
Init("0",1,ReSult);
return;
}
if(CompareBig(n1,n2) == -1) //相等
{
Init("1",1,ReSult);
ReSult->flag = flag;
return;
}
int len1 = strlen(str1) - 1;//这里长度减一只是为了直接移到数组的末尾
int len2 = strlen(str2) - 1;
int cl = len1 - len2; //被除数和除数的长度的差值
for(int i = 0; i < cl; i++)
{
strcat(str2,"0");
}
Big t1,t2; //存放现在的被除数和除数
t1 = n1;
t1.flag = 1;
t2.flag = 1;
strcpy(t2.num,str2);
int len = strlen(str2) - 1; //放除数现在的长度
Big one;
Init("1",1,&one);
Big quotient;
Big Re;
Init("0",1,"ient);
Init("0",1,&Re);
for(int nl = strlen(t2.num) -1 ; nl >=len2; nl--)
{
if(CompareBig(t1,t2) == 1)//当被除数大于被除数的时候
{
while(1)//进行一次中减法运算
{
Sub(t1,t2,&t1);
//printf("相减的结果 %s\n",t1.num);
if(t1.flag == 0)
{
strcpy(t1.num,str3);
t1.flag = 1;
break;
}
if(0 !=t1.flag)//当相减后的结果不为负数的时候进行 商自加一
{
//quotient++;
Add(quotient,one,"ient);//进行商的运算
}
if(0 == strcmp(t1.num,"0")) //当相减的结果为0的时候
{
int kk =(strlen(t2.num)-1)-len2;
for(int ni = 0; ni <kk; ni++)
{
strcat(quotient.num,"0");
}
printf("商111 %s\n",quotient.num);
Add(Re,quotient,&Re);
//printf("ii %s\n",Re.num);
ReSult->flag = 1;
*ReSult = Re;
return;
}
strcpy(str3,t1.num);
}//进行一次运算后 然后再进行特殊处理
int kk =(strlen(t2.num)-1)-len2;
for(int ni = 0; ni <kk; ni++)
{
strcat(quotient.num,"0");
}
Add(Re,quotient,&Re);
Init("0",1,"ient);
}
DelLastSero(t2.num);//除数删除一位
}
ReSult->flag = flag;
*ReSult = Re;
}
void Mod(Big n1,Big n2,Big * ReSult)
{
char str1[MAX_BIG];
char str2[MAX_BIG];
char str3[MAX_BIG];
memset(str2,0,sizeof(str2));
memset(str3,0,sizeof(str3));
int flag = 1;
n1.flag = 1;
n2.flag = 1;
strcpy(str1,n1.num);
strcpy(str2,n2.num);
//int l,k,re; //存放数字
if(strcmp(n2.num,"0") == 0)
{
puts("除数不能为0");
exit(3);
}
if(n1.flag*n2.flag == 0)
{
puts("Mod 不能为负数");
exit(3);
}
if(CompareBig(n1,n2) == 0)//小于
{
*ReSult = n1;
return;
}
if(CompareBig(n1,n2) == -1) //相等
{
Init("0",1,ReSult);
//ReSult->flag = flag;
return;
}
int len1 = strlen(str1) - 1;//这里长度减一只是为了直接移到数组的末尾
int len2 = strlen(str2) - 1;
int cl = len1 - len2; //被除数和除数的长度的差值
for(int i = 0; i < cl; i++)
{
strcat(str2,"0");
}
Big t1,t2; //存放现在的被除数和除数
t1 = n1;
t1.flag = 1;
t2.flag = 1;
strcpy(t2.num,str2);
int len = strlen(str2) - 1; //放除数现在的长度
Big one;
Init("1",1,&one);
Big quotient;
Big Re;
Init("0",1,"ient);
Init("0",1,&Re);
for(int nl = strlen(t2.num) -1 ; nl >=len2; nl--)
{
if(CompareBig(t1,t2) == 1)//当被除数大于被除数的时候
{
while(1)//进行一次中减法运算
{
Sub(t1,t2,&t1);
//printf("相减的结果 %s\n",t1.num);
if(t1.flag == 0)
{
strcpy(t1.num,str3);
t1.flag = 1;
break;
}
if(0 !=t1.flag)//当相减后的结果不为负数的时候进行 商自加一
{
//quotient++;
Add(quotient,one,"ient);//进行商的运算
}
if(0 == strcmp(t1.num,"0")) //当相减的结果为0的时候
{
int kk =(strlen(t2.num)-1)-len2;
for(int ni = 0; ni <kk; ni++)
{
strcat(quotient.num,"0");
}
//printf("商111 %s\n",quotient.num);
//Add(Re,quotient,&Re);
//printf("ii %s\n",Re.num);
ReSult->flag = 1;
*ReSult = t1;
return;
}
strcpy(str3,t1.num);
}//进行一次运算后 然后再进行特殊处理
int kk =(strlen(t2.num)-1)-len2;
for(int ni = 0; ni <kk; ni++)
{
strcat(quotient.num,"0");
}
Add(Re,quotient,&Re);
Init("0",1,"ient);
}
DelLastSero(t2.num);//除数删除一位
}
ReSult->flag = flag;
*ReSult = t1;
}