当前位置:文档之家› 大数的表示

大数的表示

成绩评定教师签名嘉应学院计算机学院实验报告课程名称:离散数学开课学期:2017-2018学年第1学期班级:指导老师:实验题目:大数的表示学号:姓名:一、实验目的:1.掌握大数运算的实现方法2.理解大数算法二、实验内容大数运算加减乘除和阶乘的算法实现三、上机环境VS2008四、实验过程描述1.大数存储的实现简单来说,大数算法就是模拟人类的运算过程。

作为实现大数存储最常见的一类方法是利用数组。

将一个有 n 位的大数存入数组 ,每个数组的一个元素表示一位十进制数 ,若是 n 没有超过普通 PC 机允许的定义范围 ,这种算法是简单易行的。

如果出现超大数 ,则可以采用万进制的方法加以存储。

2.大数算法(1)大数阶乘原理:把整个数组看成一个数字,这个数字和一个数相乘的时候,需要每一位都和这个乘数进行相乘运算还需要把前一为的进位加上。

运算方法和小学数学是一样的,乘积的个位是当前位上应该表示的数字,10位以上的需要进位。

因为乘数不可能大于10000,所以乘数和一个小于10的书相乘的时候不会大于100000,再加上前一位的进位用一个int型数据来保持这个结果就没有问题。

写法如下:int 结果 = result[x] * 乘数 + 进位;每一位的计算结果有了,把这个结果的个位数拿出来放到这个数组元素上:result[x] = 结果%10;接下来的工作就是计算出进位:进位 = 结果 / 10;这样一位一位的把整个数组计算一遍,最后可能还有进位,用同样的方法,把进位的数值拆成单个数字,放到相应的数组元素中。

最后输出一下结果,从最高位吧数字打印一遍就OK了。

源代码:#include <iostream>using namespace std;int main(){int n,i,j;while (cin>>n){int digit=1; //结果实时位数,也就是结果长度int carry=0; //设置进位int temp=0; //临时结果,int str[40000]; //根据题目要求设置数组的大小str[0]=1;for (i=2;i<=n;i++) //从2开始计算阶乘{for (j=1;j<=digit;j++) //根据进位digit大小来判断当前阶乘结果的的位数,递增的被乘数不存在数组中,大数阶乘只需一个数组 {temp=str[j-1]*i+carry; //当前结果的数组的每位结果str[j-1]=temp%10; //获得个位数carry=temp/10; //获得进位,可能为多位}while (carry) //当进位大于一时将结果扩展到下一位,仅对最高位做判断,{digit++;str[digit-1]=carry%10; //高位数往后移carry/=10; //当被乘数是多位数时,每次相乘的进位可能是十位百位}}for (i=digit-1;i>=0;i--) //将结果数组倒序输出,注意最后一位是"i=digit-1",因为"digit=1" 对应str[0],以此类推{cout<<str[i];}cout<<endl;}return 0;}(2)大数加法原理:两个大数我们可以用数组来保存,然后在数组中逐位进行相加,再判断该位相加后是否需要进位,为了方便计算,我们将数字的低位放在数组的前面,高位放在后面。

源代码:#include<stdio.h>#include<string.h>#define MAX 1000 // 大数的最大位数/*大数加法参数:num1为第一个大数,用字符数组保存num2为第二个大数sum数组保存相加的结果即:num1+num2=sum返回值:返回数组sum的有效长度,即计算结果的位数*/int Addition(char num1[], char num2[], int sum[]){int i, j, len;int n2[MAX] = {0};int len1 = strlen (num1); // 计算数组num1的长度,即大数的位数 int len2 = strlen (num2); // 计算数组num2的长度,即大数的位数len = len1>len2 ? len1 : len2; // 获取较大的位数//将num1字符数组的数字字符转换为整型数字,且逆向保存在整型数组sum 中,即低位在前,高位在后for (i = len1-1, j = 0; i >= 0; i--, j++)sum[j] = num1[i] - '0';// 转换第二个数for (i = len2-1, j = 0; i >= 0; i--, j++)n2[j] = num2[i] - '0';// 将两个大数相加for (i = 0; i <= len; i++){sum[i] += n2[i]; // 两个数从低位开始相加if (sum[i] > 9) // 判断是否有进位{ // 进位sum[i] -= 10;sum[i+1]++;}}if(sum[len] != 0) // 判断最高位是否有进位len++;return len; // 返回和的位数}int main(){int i, len;int sum[MAX] = {0}; // 存放计算的结果,低位在前,高位在后,即sum[0]是低位char num1[] = "1234567891234567891234"; // 第一个大数char num2[] = "2345678912345678913345"; // 第二个大数len = Addition(num1, num2, sum); // 两数相加printf("%s\n +\n%s\n =\n", num1, num2);// 反向输出求和结果for (i = len-1; i >= 0; i--)printf("%d", sum[i]);printf("\n");return 0;}(3)大数减法原理:相减算法也是从低位开始减的。

先要判断被减数和减数哪一个位数长,若被减数位数长是正常的减法;若减数位数长,则用被减数减去减数,最后还要加上负号;当两数位数长度相等时,最好比较哪一个数字大,否则负号处理会很繁琐;处理每一项时要,如果前一位相减有借位,就先减去上一位的借位,无则不减,再去判断是否能够减开被减数,如果减不开,就要借位后再去减,同时置借位为1,否则置借位为0。

源代码:#include<stdio.h>#include<string.h>#define MAX 1000 // 大数的最大位数/*大数减法参数:num1为被减数,用字符数组保存num2为减数sum数组保存相减的结果即:num1-num2=sum返回值:返回数组sum的有效长度,即计算结果的位数*/int Subtraction(char num1[], char num2[], int sum[]){int i, j, len, blag;char *temp;int n2[MAX] = {0};int len1 = strlen(num1); // 计算数组num1的长度,即大数的位数int len2 = strlen(num2); // 计算数组num2的长度,即大数的位数// 在进行减法之前要进行一些预处理blag = 0; // 为0表示结果是正整数,为1表示结果是负整数if(len1 < len2) // 如果被减数位数小于减数{blag = 1; // 标记结果为负数// 交换两个数,便于计算temp = num1;num1 = num2;num2 = temp;len = len1;len1 = len2;len2 = len;}else if(len1 ==len2) // 如果被减数的位数等于减数的位数{// 判断哪个数大for(i = 0; i < len1; i++){if(num1[i] == num2[i])continue;if(num1[i] > num2[i]){blag = 0; // 标记结果为正数break;}else{blag = 1; // 标记结果为负数// 交换两个数,便于计算temp = num1;num1 = num2;num2 = temp;break;}}}len = len1>len2 ? len1 : len2; // 获取较大的位数//将num1字符数组的数字转换为整型数且逆向保存在整型数组sum中,即低位在前,高位在后for (i = len1-1, j = 0; i >= 0; i--, j++)sum[j] = num1[i] - '0';// 转换第二个数for (i = len2-1, j = 0; i >= 0; i--, j++)n2[j] = num2[i] - '0';// 将两个大数相减for (i = 0; i <= len; i++){sum[i] = sum[i] - n2[i]; // 两个数从低位开始相减if (sum[i] < 0) // 判断是否有借位{ // 借位sum[i] += 10;sum[i+1]--;}}// 计算结果长度for (i = len1-1; i>=0 && sum[i] == 0; i--);len = i+1;if(blag==1){sum[len] = -1; // 在高位添加一个-1表示负数len++;}return len; // 返回结果的位数}int main(){int i, len;int sum[MAX] = {0}; // 存放计算的结果,低位在前,高位在后,即sum[0]是低位char num1[] = "987654321987654321"; // 第一个大数char num2[] = "123456789123456789"; // 第二个大数len = Subtraction(num1, num2, sum); // 两数相减// 输出结果printf("%s\n -\n%s\n =\n", num1, num2);if(sum[i=len-1] < 0) // 根据高位是否是-1判断是否是负数{printf("-"); // 输出负号i--;}for (; i >= 0; i--)printf("%d", sum[i]);printf("\n");return 0;}(4)大数乘法原理:首先说一下乘法计算的算法,从低位向高位乘,在竖式计算中,我们是将乘数第一位与被乘数的每一位相乘,记录结果,之后,用第二位相乘,记录结果并且左移一位,以此类推,直到计算完最后一位,再将各项结果相加,得出最后结果。

相关主题