高精度

/*****************************************************************************************
 * 整数高精度
 * wengsht
 *
 * 基于int数组编的高精度,包括长整数+ - * / %  加减法支持非负整数  乘除支持整数域
 * 
 * 格式化操作:
 * Atoi( int [],char * )              将char * 根据进制CI 转换为int[] 数组!!/第一位标记有效位数
 *                                    !!/ 不支持输入消除前导
 * void outputf( int [] )             格式化输出
 *
 * 主要函数:
 * void add( int s1[],int s2[],int s3[] )           s1 + s2 = s3  加减法只支持非负整数
 * void sub( int s1[],int s2[],int s3[] )           s1 - s2 = s3 ( s1<s2 符号位s[大大的数] 置)
 * void mul( int s1[],int s2[],int s3[] )           s1 * s2 = s3  乘除法支持负数
 * void div( int s1[],int s2[],int s3[],int s4[] )  s1 / s2 = s3 ; s1 % s2 = s4
 * int mod( int s[],int num )                       return s % num;  一般取余的除数不超过位的
 *
 * 辅助:
 * bool less( int s1[],int s2[] )     顾名思义
 * bool nolarger( int s1[],int s2[] )
 * Left_move ( int s[] )              s *= CI
 * 
 ******************************************************************************************/

#include <iostream>
#include <cstring>
#include <iomanip>
#include <cstdio>
using namespace std;

const int size = 101; //第一位(s[0])标记有效位数,最后一位标记符号位
const int CI = 10000; //数组每位考虑乘法只能设那么大
int  s1[size],s2[size],s3[size],s4[size],s5[size],s6[size];   // s1 op s2 = s3 s1 % s2 = s4   
															  //!! 实际上乘法时size不可能全用,想少bug把size调大就可以了
                                                              // s5/s6用于除法中暂存数据
char ss[size+1];      //接收输入
int d[4] = { 1,10,100,1000 };

bool _less( int s1[],int s2[] )   //减法、除法比较时用
{  
    if( s1[0] != s2[0] ) return s1[0] < s2[0];
    for( int i = s1[0];i >= 1;i-- )
    {
        if( s1[i] != s2[i] ) return s1[i] < s2[i] ;
    }
    return false;
}
bool nolarger( int s1[],int s2[] )
{
    if( s1[0] != s2[0] ) return s1[0] < s2[0];
    for( int i = s1[0];i >= 1;i-- )
    {
        if( s1[i] != s2[i] ) return s1[i] < s2[i] ;
    }
    return true;
}
void Left_move( int s[] )          //左移s = s * 10000
{
	if( s[s[0]] == 0 ) return ;
	int l = ++s[0];
	for( ;l > 1;l-- ) s[l] = s[l-1];
	s[1] = 0;
}
void AtoI( int s[],char *ss )      //将ss 格式为int[]
{
	memset( s,0,sizeof(s)*size ); s[0] = 1; 
	int l = strlen( ss );
	if( ss[0] == '-' )  //处理下输入的负数,
		                //只在* /中利用,+ - 法就不用了吧= = 挺容易在主函数中处理的
	{
		s[size-1] = 1;
		for( int i = 0;i < l-1;i++ ) ss[i] = ss[i+1]; 
		l--;
	}
	int j = 0; //CI为,满进
	for( int i = l-1;i >= 0;i-- )
	{
		s[s[0]] = s[s[0]] + (ss[i]-'0') * d[j++];
		if( j > 3 && i > 0) { j = 0;s[0]++; } 
	}
}
void outputf( int s[] )   //格式化输出
{
	if( s[size-1] ) cout<<'-'; 
	int i = s[0];
	cout<<s[i];
	for( i--;i >= 1;i-- ) cout<<setfill( '0' )<<setw(4)<<s[i];  //非最高位要补齐
}

void add( int s1[],int s2[],int s3[] )  //s1 + s2 = s3
{
	memset( s3,0,sizeof(int)*size );
	
	int i = 1;
	while( i <= s1[0] || i <= s2[0] ) 
	{
		s3[i] += ( s1[i] + s2[i] );
		if( s3[i++] >= CI )
		{
			s3[i]++;
			s3[i-1] -= CI;
		}
	}
	s3[0] = s3[i] > 0 ? i:i-1;
}
void sub( int s1[],int s2[],int s3[] )  // s1 - s2 = s3
{
	memset( s3,0,sizeof(int)*size ); 
	
	if( _less(s1,s2) ) { swap( s1,s2 ); s3[size-1] = 1; }
	
	int i = 1;
	while( i <= s1[0] )
	{
		s3[i] = s3[i] + s1[i] - s2[i];

		if( s3[i++] < 0 ) 
		{
			s3[i-1] += 10000;
			s3[i]--;
		}
	}
	while( !s3[i] && i > 1 ) i--;
	s3[0] = i;
}
void mul( int s1[],int s2[],int s3[] ) // s1 * s2 == s3
{
	memset( s3,0,sizeof(int)*size );

	if( s1[size-1] && !s2[size-1] || !s1[size-1] && s2[size-1] ) s3[size-1] = 1;  //符号位
	for( int i = 1;i <= s1[0];i++ )
	{
		for( int j = 1;j <= s2[0];j++ )
		{
			int k = i+j-1;
			s3[k] += ( s1[i] * s2[j] );
			if( s3[k] > CI ) 
			{
				s3[k+1] += (s3[k] / CI );
				s3[k] %= CI;
			}
		}
	}
	s3[0] = s1[0]+s2[0]-1;
	if( s3[s3[0]+1] ) s3[0]++;
	while( !s3[s3[0]] && s3[0] > 1 ) s3[0]--;   // 去前导
	
}
long long mod ( int s[],long long num )
{
	long long result = 0;
	if( !num ) return 0;
	if( num < 0 ) num = -num;

	for( int i = s[0];i >= 1;i-- )
	{
		result = (result * CI + s[i] ) % num;
	}
	if( s[size-1] ) result = -result;

	return result;
}
void div( int s1[],int s2[],int s3[],int s4[] ) //s3 -> 商s4 -> 余数
{
	memset( s3,0,sizeof(int)*size );
	memset( s4,0,sizeof(int)*size );
	
	for( int i = s1[0];i >= 1;i-- )
	{
		//itoa( s1[i],ss,10 );
		sprintf(ss, "%d",s1[i]);
		AtoI( s5,ss );
	
		Left_move( s4 );
		
		memcpy( s6,s4,sizeof(int)*size );
		add( s6,s5,s4 );
		
		int result = 0;

		while( nolarger( s2,s4 ) )
		{
			memcpy( s6,s4,sizeof(int)*size );
			result++;
			sub( s6,s2,s4 );
		}
		Left_move( s3 );
		memcpy( s6,s3,sizeof(int)*size );
		sprintf(ss, "%d",result);
		//itoa( result,ss,10 );
		AtoI( s5,ss );
		add( s6,s5,s3 );
	}
	if( s1[size-1] && !s2[size-1] || !s1[size-1] && s2[size-1] ) s3[size-1] = 1;
	if( s1[size-1] && s4[s4[0]] != 0 ) s4[size-1] = 1;
}
		
int main()
{   
	cout<<"输入两个非负整数(测试加减):";

	scanf("%s",ss);
	AtoI( s1,ss );
	scanf("%s",ss);
	AtoI( s2,ss );
	add( s1,s2,s3 );
	outputf( s3 );cout<<endl;
	sub( s1,s2,s3);
	outputf( s3 );cout<<endl;

	cout<<"输入两个长整数(测试乘除):";
	scanf("%s",ss);
	AtoI( s1,ss );
	scanf("%s",ss);
	AtoI( s2,ss );
	mul( s1,s2,s3 );
	outputf( s3 );cout<<endl;

	div( s1,s2,s3,s4 );
	outputf(s3);cout<<" ";
	outputf(s4);cout<<endl;
	cout<<mod( s1,222)<<endl;

	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值