数学加减法编程 大整数加法c语言思路

我们知道,计算机内的数据表示只是一个有限字长的二进制序列,表达的十进制整数非常有限:
= 15 (十进制是个2位数,二进制是4位1)
= 255 (十进制是个3位数,二进制是8位1)
= 65535 (十进制是个5位数,二进制是32位1)
= 4294967295 (十进制是个10位数,二进制是32位1)
18446744073709551615 (十进制是个20位数,二进制是64位1)
可以看出,通常一位十进制数需要3.2位二进制数来表示 。
相对于整型,数组或字符串可以表示更多的十进制位数,计算时做转换即可 。或者链式存储数据块(如一个数据块存储4位数) 。
对于浮点数,可以表示更大的数字,但精度有限 。

浮点数的位数分为三部分:符号位、阶码、尾码;阶码决定值域,尾码决定精度 。
float: 1bit(符号位) 8bits(指数位) 23bits(尾数位)
double: 1bit(符号位) 11bits(指数位) 52bits(尾数位)
于是,float的指数范围为-127~+128,而double的指数范围为-1023~+1024,并且指数位是按补码的形式来划分的 。
【数学加减法编程 大整数加法c语言思路】其中负指数决定了浮点数所能表达的绝对值最小的非零数;而正指数决定了浮点数所能表达的绝对值最大的数,也即决定了浮点数的取值范围 。


float和double的精度是由尾数的位数来决定的 。浮点数在内存中是按科学计数法来存储的,其整数部分始终是一个隐含着的“1”,由于它是不变的,故不能对精度造成影响 。
float:2^23 = 8388608,一共七位,这意味着最多能有7位有效数字,但绝对能保证的为6位,也即float的精度为6~7位有效数字;
double:2^52 = 4503599627370496,一共16位,同理,double的精度为15~16位 。(52/3.2≈16)
1 利用链式存储数据块来模拟大整数加数
首先采用一个带有表头结点的环形链来表示一个非负的超大整数,如果从低位开始为每个数字编号,则第1~4 位、第5~8 位……的每4 位组成的数字,依次放在链表的第1 个、第2 个……第n 结点中,不足4 位的最高位存放在链表的最后一个结点中,表头结点的值规定为-1 。例如:大整数“587890987654321”可用如下的带表头结点head 的链表表示 。
数学加减法编程 大整数加法c语言思路

文章插图
按照此数据结构,可以从两个表头结点开始,顺序依次对应相加,求出所需要的进位后,代入下一个结点的运算 。
#include<stdio.h>#include<stdlib.h>#define HUNTHOU 10000typedef struct node{ int data; struct node *next;}NODE; /*定义链表结构*/NODE *insert_after(NODE *u,int num); /*在u结点后插入一个新的NODE,其值为num*/NODE *addint(NODE *p,NODE *q); /*完成加法操作返回指向*p+*q结果的指针*/void printint(NODE *s);NODE *inputint(void);void main(){ NODE *s1,*s2,*s; NODE *inputint(), *addint(), *insert_after(); puts("*********************************************************"); puts("* This program is to calculate *"); puts("* the addition of king sized positive integer. *"); puts("*********************************************************"); printf(" >> Input S1= "); s1=inputint(); /*输入被加数*/ printf(" >> Input S2= "); s2=inputint(); /*输入加数*/ printf(" >> The addition result is as follows.\n\n"); printf(" S1= "); printint(s1); putchar('\n'); /*显示被加数*/ printf(" S2= "); printint(s2); putchar('\n'); /*显示加数*/ s=addint(s1,s2); /*求和*/ printf(" S1+S2="); printint(s); putchar('\n'); /*输出结果*/ printf("\n\n Press any key to quit..."); getch();}NODE *insert_after(NODE *u,int num){ NODE *v; v=(NODE *)malloc(sizeof(NODE)); /*申请一个NODE*/ v->data=http://www.baifabohui.com/smjk/num; /*赋值*/ u->next=v; /*在u结点后插入一个NODE*/ return v;}NODE *addint(NODE *p,NODE *q) /*完成加法操作返回指向*p+*q结果的指针*/{ NODE *pp,*qq,*r,*s,*t; int total; // 两数相加的和 int remain; // total%10000的结果 int carry; // total/10000的结果 pp=p->next; qq=q->next; s=(NODE *)malloc(sizeof(NODE)); /*建立存放和的链表表头*/ s->data=-1; t=s; carry=0; /*carry:进位*/ while(pp->data!=-1&&qq->data!=-1) /*均不是表头*/ { total=pp->data+qq->data+carry; /*对应位与前次的进位求和*/ remain=total%HUNTHOU; /*求出存入链中部分的数值 */ carry=total/HUNTHOU; /*算出进位*/ t=insert_after(t,remain); /*将部分和存入s向的链中*/ pp=pp->next; /*分别取后面的加数*/ qq=qq->next; } r=(pp->data!=-1)?pp:qq; /*取尚未自理完毕的链指针*/ while(r->data!=-1) /*处理加数中较大的数*/ { total=r->data+carry; /*与进位相加*/ remain=total%HUNTHOU; /*求出存入链中部分的数值*/ carry=total/HUNTHOU; /*算出进位*/ t=insert_after(t,remain); /*将部分和存入s指向的链中*/ r=r->next; /*取后面的值*/ } if(carry) t=insert_after(t,1); /*处理最后一次进位*/ t->next=s; /*完成和的链表*/ return s; /*返回指向和的结构指针*/}NODE *inputint(void) /*输入超长正整数*/{ NODE *s,*ps,*qs; struct remain { int num; struct remain *np; }*p,*q; int i,j,k; long sum; char c; p=NULL; /*指向输入的整数,链道为整数的最低的个位,链尾为整数的最高位*/ while((c=getchar())!='\n') /*输入整数,按字符接收数字*/ if(c>='0'&&c

推荐阅读