高精度运算

VonGang原创,如有错误,欢迎指正。转载请注明:http://www.cnblogs.com/vongang/

                                                                                                                                               

                                                                                                                                           

                                                                                                                                            

当对很大的数(比如100位)进行运算时,肯定不能c/c++内的数据类型直接运算(当然Java里的BigNumber可以。。。)这时就要用数组模拟运算过程。+, - ,*, /,运算貌似是小学学的东西,童鞋们,现在要用到小学的知识啦!!
先说加法,大体的操作包括逆序、对位、求和、进位(其实就是小学的加法运算,不过是把数倒过来算,至于为什么要逆序。。。)

例题:http://poj.grids.cn/practice/2981

代码:

#include <stdio.h>
#include
<string.h>
#define MAX 200
int an1[MAX+10];
int an2[MAX+10];
char s1[MAX+10];
char s2[MAX+10];
int main()
{
scanf(
"%s", s1);
scanf(
"%s", s2);
int i, j;
memset( an1,
0, sizeof(an1));
memset( an2,
0, sizeof(an2));
int len1 = strlen( s1);
j
= 0;
for( i = len1 - 1;i >= 0 ; i --) //逆置
an1[j++] = s1[i] - '0';
int len2 = strlen(s2);
j
= 0;
for( i = len2 - 1;i >= 0 ; i --) //逆置
an2[j++] = s2[i] - '0';
len1
= len1 > len2 ? len1 : len2;
for( i = 0;i < len1 ; i ++ )
{
an1[i]
+= an2[i]; //求和
if( an1[i] >= 10 ) //进位
{
an1[i]
-= 10;
an1[i
+1] ++;
}
}
int flag = 0;
for (i = len1 ; i >= 0; i--) //输出
{
if (flag || an1[i])
{
flag
= 1;
printf(
"%d",an1[i]);
}
}
if (!flag)
{
printf(
"0");
}
printf(
"\n");
return 0;
}

减法同加法类似

例题:http://poj.grids.cn/practice/2736

代码:

#include <stdio.h>
#include
<string.h>
#define MAX 200
int an1[MAX+10];
int an2[MAX+10];
char s1[MAX+10];
char s2[MAX+10];
int main()
{
int i, j;
int n;
scanf(
"%d",&n);
while(n--)
{
scanf(
"%s", s1);
scanf(
"%s", s2);
memset( an1,
0, sizeof(an1));
memset( an2,
0, sizeof(an2));
int len1 = strlen( s1);
j
= 0;
for( i = len1 - 1;i >= 0 ; i --)
an1[j
++] = s1[i] - '0';
int len2 = strlen(s2);
j
= 0;
for( i = len2 - 1;i >= 0 ; i --)
an2[j
++] = s2[i] - '0';
for( i = 0;i < len1 ; i ++ )
{
an1[i]
-= an2[i];
if( an1[i] < 0 )
{
an1[i]
+= 10;
an1[i
+1] --;
}
}
int flag = 0;
for (i = len1 ; i >= 0; i--)
{
if (flag || an1[i])
{
flag
= 1;
printf(
"%d",an1[i]);
}
}
if (!flag)
{
printf(
"0");
}
if(n != 0)
printf(
"\n");
}
printf(
"\n");
return 0;
}

乘法同加法类似,不过进位时mod10而不是 -10:

例题:http://poj.grids.cn/practice/2980

代码:

#include <stdio.h>
#include
<string.h>
#define max 200
int an1[max+10];
int an2[max+10];
int result[max*2+10];
char s1[max+10];
char s2[max+10];
int main()
{
gets(s1);
gets(s2);
int i, j;
memset(an1,
0,sizeof(an1));
memset(an2,
0,sizeof(an2));
memset(result,
0,sizeof(result));
int len1 = strlen(s1);
j
= 0;
for(i = len1-1; i >= 0; i--)
an1[j
++] = s1[i] - '0';
int len2 = strlen(s2);
j
= 0;
for(i = len2-1; i >= 0; i--)
an2[j
++] = s2[i] - '0';
for(i = 0; i < len2; i++)
for(j = 0; j < len1; j++)
result[i
+j] += an2[i]*an1[j];
for(i = 0; i < len1*len2; i++)
{
if(result[i] >= 10)
{
result[i
+1] += result[i]/10;
result[i]
%= 10;
}
}
int flag = 0;
for(i = len1*len2; i >= 0; i--)
{
if(flag)
printf(
"%d",result[i]);
else if(result[i])
{
printf(
"%d",result[i]);
flag
= 1;
}
}
if(!flag)
printf(
"0");
printf(
"\n");
return 0;
}

除法:

除法可以看作是循环相减,不过在做减法之前有一个判断两数大小的操作;

还是例题:http://poj.grids.cn/practice/2737
代码:

#include <stdio.h>
#include
<string.h>
#define max 200
char s1[max + 10];
char s2[max + 10];
int an1[max + 10];
int an2[max + 10];
int result[max + 10];
int jianfa(int a[], int b[], int len1, int len2)
{
int i;
if(len1 < len2) //----------以下判断大小-------------
return -1;
int flag = 0;
if(len1 == len2)
{
for(i = len1 - 1; i >= 0; i--)
{
if(a[i] > b[i])
flag
= 1;
else if(a[i] < b[i])
{
if(!flag) return -1;
}
}
}
//-------------以上判断大小-------------
for(i = 0; i < len1; i++)//减法
{
a[i]
-= b[i];
if(a[i] < 0)
{
a[i]
+= 10;
a[i
+1]--;
}
}
for(i = len1 - 1; i >= 0; i--)
if(a[i])
return i+1;
return 0;
}
int main()
{
int i, j, n;
scanf(
"%d",&n);
while(n--)
{
scanf(
"%s",s1);
scanf(
"%s",s2);
memset(an1,
0, sizeof(an1));
memset(an2,
0, sizeof(an2));
memset(result,
0, sizeof(result));
int len1 = strlen(s1);
j
= 0;
for(i = len1 - 1; i >= 0; i--)
an1[j
++] = s1[i] - '0';
int len2 = strlen(s2);
j
= 0;
for(i = len2 - 1; i >= 0; i--)
an2[j
++] = s2[i] - '0';
if(len1 < len2)
{
printf(
"0\n");
continue;
}
len1
= jianfa(an1, an2, len1, len2);
if(len1 < 0)
{
printf(
"0\n");
continue;
}
else if(len1 == 0)
{
printf(
"1\n");
continue;
}
result[
0]++; //减掉一次,商加1
//减去一次后结果的长度是len1
int n = len1 - len2;
if(n < 0) //不能再减时
{
for(i = 0;i < max; i++)
{
if(result[i] >= 10)
{
result[i
+1] += result[i]/10;
result[i]
%= 10;
}
}
}
else if(n > 0)
{
for(i = len1 - 1; i >= 0; i--)
{
if(i >= n)
an2[i]
= an2[i-n];
else
an2[i]
= 0;
}
}
len2
= len1;
for(j = 0; j <= n; j++)
{
int t;
while((t = jianfa(an1, an2+j, len1, len2-j)) >= 0)
// an2+j 表示把数组的头指针向后移j个位置,即删掉j个an2补上的0
// len2 同时减小j
{
len1
= t;
result[n
-j]++;
}
}
for(i = 0;i < max; i++)//进位
{
if(result[i] >= 10)
{
result[i
+1] += result[i]/10;
result[i]
%= 10;
}
}
int flag = 0;
for(i = max; i >= 0; i--)//输出
if(flag)
printf(
"%d",result[i]);
else if(result[i])
{
printf(
"%d",result[i]);
flag
= 1;
}
if(!flag)
printf(
"0\n");
printf(
"\n");
}
return 0;
}



posted @ 2011-08-17 16:55  AC_Von  阅读(378)  评论(0编辑  收藏  举报