C语言_超大数四则运算
大数加法
void Add(char s1[],char s2[])//参数为两个字符串数组 { int num1[M],num2[M]; int i,j; len1 = strlen (s1); len2 = strlen (s2); for (i = len1-1,j = 0; i >= 0; i --)//num1[0]保存的是低位 num1[j++] = s1[i] - '0'; for (i = len2-1,j = 0; i >= 0; i --) num2[j++] = s2[i] - '0'; for (i = 0; i < M; i ++) { num1[i] += num2[i]; if (num1[i] > 9) { num1[i] -= 10; num1[i+1] ++; } }
for (i = M-1; (i >= 0)&&(num1[i] == 0); i --) ;//找到第一个不是 0的数的位置 if (i >= 0) //从高位到低位输出每个数 for (; i >= 0; i --) printf ("%d",num1[i]); else printf ("0\n"); }
1. 再下来算4×3。此处4×3 的结果代表12 个 100,因此要 aResult[2]+= 12,变为:
2. 最后算 4×8。此处4×8 的结果代表 32 个 1000,因此要 aResult[3]+= 32,变为:
1. 乘法过程完毕。接下来从 aResult[0]开始向高 位逐位处理进位问题。aResult[0]留下5,把4 加到aResult[1]上,aResult[1]变为51 后,应 留下1,把5 加到aResult[2]上……最终使得 aResult 里的每个元素都是1 位数,结果就算出 来了:
大数除法
幂运算的实现
幂的实现是最为简单的了,国为有了前面 的算法做铺垫,就是调用乘法函数,来循 环去自乘,幂指数相应减1,直到幂指数变 为0时结束。
减法运算的实现 算法也是从低位开始减。先要判断减数和被减 数那一个位数长,减数位数长是正常减;被减 数位数长,则被减数减减数,最后还要加上负 号;两数位数长度相等时,最好比那一个数字 大,否则负号处理会很繁琐;处理每一项时要 ,如果前一位相减有借位,就先减去上一位的 借位,无则不减,再去判断是否能够减开被减 数,如果减不开,就要借位后再去减,同时置 借位为1,否则置借位为0。
减法运算的实现
-
减数
7
6
9
8
7
7
5
6
4
5
3
4
4
3
3
2
2
0
0
被减数 8
9
1、借位为1
6
2、借位为1
初始化借位为0,各对应 位相减后再减上借位数
0
3、借位为0
2
4、借位ቤተ መጻሕፍቲ ባይዱ0
由低位向高位相加计算,直至所有运算结束
处理中注意问题:
如果被减数大于减数时 ,交换两个数再相减, 最后加个“-”号即可
1
2
结果可能会出现前面是 一堆0的情况,要处理好 ,如当减数为112,而被 减数为111时,会出现 001
总结一个规律:即一个数的第i 位和另一个数的第j 位相乘所得的数,一定是要累加到结果的第i+j 位上。这里i, j 都是从右往左,从0 开始数。 ans[i+j] = a[i]*b[j];
处理中注意问题:
1
另外进位时要处理,当前的值加 上进位的值再看本位数字是否又 有进位;前导清零。
大数乘法
请计算: 1、 2 的 1000次幂 2、 2 的 10000次幂 3、 1234567890123456789123456789034 53434534534535345434543 乘上 9387429387492873492873402803482 0938479288374892733453453534
主要内容
1
2 3 4 5 6
数字存储的实现 加法运算的实现
减法运算的实现
乘法运算的实现 除法运算的实现
幂运算的实现
数字存储的实现 大数计算的因数和结果精度一般是少则数 十位,多则几万位。在C/C++语言中定义 的类型中精度最多只有二十多位。一般我 们称这种基本数据类型无法表示的整数为 大整数。如何表示和存放大整数呢?基本 的思想就是:用数组存放和表示大整数。 一个数组元素,存放大整数中的一位。 比如:1664434318
void Multi(char str1[],char str2[]) { int len1,len2,i,j; int a[MAX+10],b[MAX+10],c[MAX*2+10]; memset (a,0,sizeof(a)); memset (b,0,sizeof(b)); memset (c,0,sizeof(c)); len1=strlen(str1); for(j=0,i=len1-1; i>=0; i--)//把数字倒过来 a[j++]=str1[i]-'0'; len2=strlen(str2); for(j=0,i=len2-1; i>=0; i--)//倒转第二个整数 b[j++]=str2[i]-'0'; for(i=0; i<len2; i++)//用第二个数乘以第一个数,每次一位 for(j=0; j<len1; j++) c[i+j]+= b[i]*a[j]; //先乘起来,后面统一进位
for(i=0; i<MAX*2; i++)//循环统一处理进位问题 if(c[i]>=10) { c[i+1]+=c[i]/10; c[i]%=10; }
for(i=MAX*2; (c[i]==0)&&(i>=0); i--);//跳过高位的0 if(i>=0) for(; i>=0; i--) printf("%d", c[i]); else printf("0"); pritnf("\n");
}
除法运算的实现
首先说一下我们所要的结果,当除数除 不开被子除数时,不用除到小数,当除 数小于被除数时,除数作为余数既可, 不用再向下除了。
基本思路
基本的思想是反复做减法,看看从被除数里最多 能减去多少个除数,商就是多少。一个一个减显 然太慢,如何减得更快一些呢?以7546 除以 23 为例来看一下:开始商为0。先减去23 的 100 倍,就是2300,发现够减3 次,余下646 。于是商的值就增加300。然后用646减去230 ,发现够减2 次,余下186,于是商的值增加 20。最后用186 减去23,够减8 次,因此最终 商就是328。
超大数的四则运算
各类型的范围 int (16位) -32768~32767 (注:现在大多数的编译器的int型是32位的 也就 是说跟long型的大小一样) long long或__int64(64位) -9223372036854775808~ 9223372036854775807 float(32位) 精确到小数点后6~7位 double (64位) 精确到小数点后15~16位 (注:平时做题时 都把浮点型数据定义为double 型 避免精度不够出错)
下标
0 1
1 6
2 6
3 4
4 4
5 3
6 4
7 3
8 1
9 8
加法运算的实现
+
加数
9
9
6
8
6
7
4
6
4
5
3
4
4
3
3
2
0
0
0
被加数 1
0
1、进位为1 初始化进位为0,各对应 6 2、进位为1 位相加后再加上进位数
5
3、进位为1
2
4、进位为1
由低位向高位相加计算,直至所有运算结束
理中注意问题:
1. 判断最后数组的长度. 2. 去掉前导零
乘法运算的实现 首先说一下乘法计算的算法,从低位向高 位乘,在竖式计算中,我们是将乘数第一 位与被乘数的每一位相乘,记录结果,之 后,用第二位相乘,记录结果并且左移一 位,以此类推,直到计算完最后一位,再 将各项结果相加。得出最后结果。
计算的过程基本上和小学生列竖式做乘法相同。 为编程方便,并不急于处理进位,而将进位问题 留待最后统一处理。 ans[i+j] = a[i]*b[j];
现以 835×49 为例来说明程序的计算过。
1. 先算835×9。5×9 得到45 个1,3×9 得到27 个10,8×9 得到72 个100。由于不急于处理进 位,所以835×9 算完后,aResult 如下:
2. 接下来算4×5。此处4×5 的结果代表20 个10, 因此要 aResult[1]+=20,变为: