大整数运算问题

背景:poj 1001

Time Limit: 500MS  Memory Limit: 10000K

Description

Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the national debt is a taxing experience for many computer systems. 

This problem requires that you write a program to compute the exact value of Rn where R is a real number ( 0.0 < R < 99.999 ) and n is an integer such that 0 < n <= 25.

Input

The input will consist of a set of pairs of values for R and n. The R value will occupy columns 1 through 6, and the n value will be in columns 8 and 9.

Output

The output will consist of one line for each line of input giving the exact value of R^n. Leading zeros should be suppressed in the output. Insignificant trailing zeros must not be printed. Don’t print the decimal point if the result is an integer.

Sample Input

95.123 12

0.4321 20

5.1234 15

6.7592  9

98.999 10

1.0100 12

Sample Output

548815620517731830194541.899025343415715973535967221869852721

.00000005148554641076956121994511276767154838481760200726351203835429763013462401

43992025569.928573701266488041146654993318703707511666295476720493953024

29448126.764121021618164430206909037173276672

90429072743629540498.107596019456651774561044010001

1.126825030131969720661201

分析:先转换成大整数运算,再确定小数点位置

=====================================================================================================================

大整数运算(这里实现了相加和相乘)

 

大整数在内存中存储方法:

     采用字符串,即把处理数值改为处理字符串,因为字符串没有长度限制,且字符串中的每一字符正好可以对碰长整数中的一位数字。把长整数的加减乘除,转化为二产符串的加减乘除,需特殊处理的是:

①汁算时要把每一位字符减48转换为数值,计算后再把相应结果加48转换为字符,另外还须注意加乘进位、减借位的处理。

②采用链表,用链表的每一结点存储一位数字或多位数字。把长整数的加减乘转化为链表各结点的加减乘,进位、借位处理同上。

      链表比较灵活,添加一个值域,类型为int,这里就是使用链表实现。

 

算法介绍:

    思想:类似于手工计算的方法。

相加:先将输入的字符串转化为链表,然后创建存储和的链表,每得到一个位上的和就添加一个节点(注意进位的计算),最后可能由于加数和被加数的长度不同还剩下一部分高位的数,直接添加到链表后面。

相乘:先将输入的字符串转化为链表,然后创建存储乘积的链表,美得到一趟乘积,就加到原来结果的基础上。

例子:789*567= 447363

初始化:

789和567的链表

        5→6→7  7→8→9

存储乘积的链表

        0→0→0(长度为被乘数的字符串长度)

第1趟:567*9=5103

    直接结果510,进位5,存入新节点,变成

    0→0→0

    3→0→1→5

第2趟:567*8=4536

    3→0→1→5

          6→3→5→4

相加:

   3→6→4→0→5

第3趟:567*7=3969

   3→6→4→0→5

                9→6→9→3

    相加:

    3→6→3→7→4→4

结果(逆序):447363

=============================================================================

实现代码:

 

// 大整数运算.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<memory.h>

typedef struct mynode
{
	int data;
	struct mynode* next;
}mynode,*node;


//初始化链表
node initlink()
{
	node link;
	link=(node)malloc(sizeof(mynode));
	return link;
}

//字符串转链表
void strtolink(node* link,char* c)
{
	node charnode,phead=NULL,r=NULL;
	while(*c)
	{
		charnode=(node)malloc(sizeof(mynode));
		charnode->data=*c;
		charnode->next=phead;
		phead=charnode;
		c++;
	}
	*link=phead;
}

//链表转字符串
void linktostr(node link,char** c)
{
	char* a=(char*)malloc(200*sizeof(char));
	memset(a, 0, 200);
	char* b=a;
	while(link!=NULL)
	{
		*a=link->data+48;
		link=link->next;
		a++;
	}
	while(*b=='0')
	{
		b++;
	}
	*c=b;
}

//释放链表
void delink(node l)
{
	node a,b;
	a=l;
	while(a)
	{
		b=a->next;
		free(a);
		a=b;
	}
}

//字符串逆序
char *swapstr(char *s)
{
    //将q指向字符串最后一个字符
    char *q = s ;
    while(*q++)
        ;
    q -= 2 ; 

    //分配空间,存储逆序后的字符串。
    //char *p = new char[sizeof(char) * (q - s + 2)] ; 
	char *p = (char*)malloc(sizeof(char) * (q - s + 2)); 
    char *r = p ;

    // 逆序存储
    while(q >= s)
        *p++ = *q-- ;
    *p = '\0' ;

    return r ;
}

/////////////////////////////////////////////////////////////

//加法运算
char* add(char* a,char* b)
{
	int i=0;//进位
	int la=strlen(a),lb=strlen(b),lc=la>lb?la:lb;
	char* s=(char*)malloc(lc+2);
	node ha=initlink(),hb=initlink(),hc=NULL,p,q,h;
	strtolink(&ha,a);
	strtolink(&hb,b);
	p=ha;//p=ha->next;
	q=hb;//q=hb->next;
	while(p!=NULL&&q!=NULL)
	{
		h=(node)malloc(sizeof(mynode));
		h->data=p->data+q->data+i-96;
		i=h->data/10;
		h->data=h->data%10;
		h->next=hc;hc=h;//hc->next=h;//和节点h插入和链表hc
		p=p->next;q=q->next;
	}
	while(p!=NULL)//加数已结束,被加数还有数据
	{
		h=(node)malloc(sizeof(mynode));
		h->data=p->data+i-48;
		i=h->data/10;
		h->data=h->data%10;
		h->next=hc;
		hc=h;
		p=p->next;
	}
	while(q!=NULL)//被加数已结束,加数还有数据
	{
		h=(node)malloc(sizeof(mynode));
		h->data=q->data+i-48;
		i=h->data/10;
		h->data=h->data%10;
		h->next=hc;
		hc=h;
		q=q->next;
	}
	if(i==1)//均已结束,最高位有进位
	{
		h=(node)malloc(sizeof(mynode));
		h->data=1;
		h->next=hc;hc=h;				
	}
	linktostr(hc,&s);
	delink(ha),delink(hb);
	return s;
}

node init_lb_lisk(int n)
{	
	int ch=0;
	node head,s,r;
	head=NULL;
	r=NULL;		
	while(n--)
	{
		s=(node)malloc(sizeof(mynode));
		s->data=ch;
		if(head==NULL)
			head=s;
		else
			r->next=s;
		r=s;	
		s->next=NULL;
	}	
	return head;
}


//乘法运算
char* mul(char* a,char* b)
{	
	int i;
	int la=strlen(a),lb=strlen(b),lc=la+lb;
	char* ss=(char*)malloc(lc+1);
	node ha=initlink(),hb =initlink(),hc=init_lb_lisk(lb),p,q,l,ls,s,r;
	strtolink(&ha,a);
	strtolink(&hb,b);
	p=ha;		
	s=hc;l=hc;//乘积节点指针
	while(p!=NULL)
	{
		i=0;
		q=hb;	
		l=s;
		while(q!=NULL)
		{			
			if(l!=NULL)
			{	
				l->data=l->data+(p->data-48)*(q->data-48)+i;
				i=l->data/10;
				l->data=l->data-i*10;
				if(l->next==NULL)
				{
					r=l;				
				}
				l=l->next;									
			}			
			else
			{
				ls=(node)malloc(sizeof(mynode));				
				ls->data=(p->data-48)*(q->data-48)+i;
				i=ls->data/10;//取进位
				ls->data=ls->data-i*10;//乘积大于10时,取个位
				l=r;
				l->next=ls;				
				l=l->next;
				r=l;
				l->next=NULL;
			}			
			q=q->next;
			//l=l->next;
			//l->next=NULL;
		}
		if(i!=0)
		{
			ls=(node)malloc(sizeof(mynode));
			ls->data=i;		
			l=r;
			l->next=ls;
			l=l->next;
			r=l;
			l->next=NULL;
		}
		p=p->next;
		s=s->next;
		//k1++;
	}	
	linktostr(hc,&ss);
	delink(ha);delink(hb);delink(hc);
	ss=swapstr(ss);
	return ss;
}

//==================================================================================================

int _tmain(int argc, _TCHAR* argv[])
{
	char* a=(char*)malloc(200*sizeof(char));
	char* b=(char*)malloc(200*sizeof(char));
	while(scanf("%s %s",a,b)!=EOF)
	{
		printf("a=%s b=%s\n",a,b);
		printf("a+b=%s\n",add(a,b));
		printf("a*b=%s\n",mul(a,b));
	}

	return 0;
}

关于C++大整数运算库,可以参考下面:

C++ Big Integer Library

https://mattmccutchen.net/bigint/

《大整数运算问题》

 

    原文作者:大整数乘法问题
    原文地址: https://blog.csdn.net/congduan/article/details/7606669
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞