• 高精度算法详解 [高精的四则运算与解析]


    序言

    #1什么是高精度

    高精度算法,是一种处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几百亿的大数字。
    一般的,这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘等运算。
    对于非常庞大的数字无法在计算机中正常存储。于是,将这个数字拆开成一位一位的,或者是四位四位的存储到一个数组中, 用一个数组去表示一个数字,这样这个数字就被称为是高精度数。

    #2高精度的作用

    实际上高精度就是说参与运算的数据和运算结果的范围,超出标准数据类型能表示的数据大小范围的运算。
    这种时候,如果要得到正确的计算结果,就不能依靠普通方法实现了,而要在普通运算原理的基础上,加以辅助算法来实现超大数据的计算。
    例如:
    求两个 500 位的数据相乘的结果,这时就要用到高精度算法了。

    正文

    高精度中需要处理好的问题

    数据的接收和存贮

    当输入的数很长时,我们可以采用字符串方式输入,这样可输入数字很长的数,利用字符串函数和操作运算,将每一位数取出,存入数组中。

    字符数组储存与输入:

    void init(int a[])
    {
    	char s[1000];//通过字符数组的形式输入数字 
    	
    	gets(s);
    	
    	a[0]=strlen(s);//a[0]保存字符数组s的位数 
    	
    	for(int i=1;i<=a[0];i++)
    	{
    		a[i]=s[a[0]-i]-'0';//将字符数组转换为整形数组,并逆序储存 
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    字符串输入和存储:

    void init(int a[])
    {
    	string s;//通过字符串的形式输入数字 
    	
    	getline(cin,s);//或cin>>s; 
    	
    	a[0]=s.size();//a[0]保存字符串s的位数 或s.length(); 
    	
    	for(int i=1;i<=a[0];i++)
    	{
    		a[i]=s[a[0]-i]-'0';//将字符串转换为整形数组,并逆序储存 
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    高精度数位数的确定

    字符数组的长度:
    位数等于接收的字符数组的长度,为了节省空间和便于查找使用,将其保存在 a[0]中。a[0]=strlen(s);

    字符串的长度:
    位数等于接收的字符数串的长度,为了节省空间和便于查找使用,将其保存在 a[0]中。getline(cin,s);cin>>s;

    高精度进位,借位的处理

    加法进位:

    void jia()
    {
    	c[i]=a[i]+b[i];//对应位相加 
    	
    	if(c[i]>=10)//进位了(和大于10) 
    	{
    		c[i+1]++;//向前进一位 
    		
    		c[i]%=10;//进位后剩下的数字 
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    减法借位:

    void jian()
    {
    	if(a[i]<b[i])//不够减 
    	{
    		a[i+1]--;//向前借一位 
    		
    		a[i]+=10;//借位后加10	
    	}
    	
    	c[i]=a[i]-b[i];//对应位相减	
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    乘法进位:

    void cheng()
    {
    	c[i+j-1]=a[i]*b[j]+x+c[i+j-1];//对应位的值 
    	
    	x=c[i+j-1]/10;//进位数 
    	
    	c[i+j-1]%=10;//进位后剩下的数字 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    商和余数的求法

    商和余数处理:视被除数和除数的位数情况进行处理。

    高精度的四则运算

    高精度加法

    #include
    
    using namespace std; 
    
    int a[1000],b[1000],c[1000]; 
    
    void init1(int a[])
    {
    	char s[1000];//通过字符数组的形式输入数字 
    	
    	gets(s);
    	
    	a[0]=strlen(s);//a[0]保存字符数组s的位数 
    	
    	for(int i=1;i<=a[0];i++)
    	{
    		a[i]=s[a[0]-i]-'0';//将字符数组转换为整形数组,并逆序储存 
    	}
    }
    
    void init2(int a[])
    {
    	string s;//通过字符串的形式输入数字 
    	
    	getline(cin,s);//或cin>>s; 
    	
    	a[0]=s.size();//a[0]保存字符串s的位数 或s.length(); 
    	
    	for(int i=1;i<=a[0];i++)
    	{
    		a[i]=s[a[0]-i]-'0';//将字符串转换为整形数组,并逆序储存 
    	}
    }
    
    void jiafa(int a[],int b[],int c[])
    {
    	int x=0;//暂存进位,从0开始  
    	int i=1;//位数的下标 
    	
    	while(i<=a[0]||i<=b[0])
    	{
    		c[i]=a[i]+b[i]+x;//对应位相加+上一次的位数 
    		
    		x=c[i]/10;//进位 
    		
    		c[i]=c[i]%10;//进位后剩下的数字 
    		
    		i++;//模拟下一位 
    	}
    	
    	c[i]=x;//最后的位数 
    	c[0]=i;//将和c的位数统一保存在c[0]中 
    }
    
    void aa(int a[])//删除数组a的前导0 
    {
    	while(a[0]>=1&&a[a[0]]==0)
    	{
    		a[0]--;	
    	}	
    } 
    
    int main()
    {
    	init1(a);
    	init1(b);//输入	
    	
    	aa(a);
    	aa(b);//删除前导0
    	
    	jiafa(a,b,c);//a+b=c
    	
    	aa(c);//删除c的前导0
    	
    	for(int i=c[0];i>=1;i--)
    	{
    		cout<<c[i];//输出每一位	
    	} 
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    注意: 两个数相加,结果的位数,应该比两个数中大的那个数多一位。

    高精度减法:

    #include
    
    using namespace std; 
    
    int a[1000],b[1000],c[1000]; 
    
    void init1(int a[])
    {
    	char s[1000];//通过字符数组的形式输入数字 
    	
    	gets(s);
    	
    	a[0]=strlen(s);//a[0]保存字符数组s的位数 
    	
    	for(int i=1;i<=a[0];i++)
    	{
    		a[i]=s[a[0]-i]-'0';//将字符数组转换为整形数组,并逆序储存 
    	}
    }
    
    void init2(int a[])
    {
    	string s;//通过字符串的形式输入数字 
    	
    	getline(cin,s);//或cin>>s; 
    	
    	a[0]=s.size();//a[0]保存字符串s的位数 或s.length(); 
    	
    	for(int i=1;i<=a[0];i++)
    	{
    		a[i]=s[a[0]-i]-'0';//将字符串转换为整形数组,并逆序储存 
    	}
    }
    
    void jianfa(int a[],int b[],int c[])
    {
    	int i=1;//位数的下标 
    	
    	while(i<=a[0])
    	{
    		if(a[i]<b[i])
    		{
    			a[i+1]--;//借位 
    			
    			a[i]+=10;
    		}
    		
    		c[i]=a[i]-b[i];
    		
    		i++;
    	}
    	
    	c[0]=i;//将差c的位数保存在c[0]中 
    }
    
    void aa(int a[])//删除数组a的前导0 
    {
    	while(a[0]>=1&&a[a[0]]==0)
    	{
    		a[0]--;	
    	}	
    } 
    
    int main()
    {
    	init1(a);
    	init1(b);//输入
    	
    	jianfa(a,b,c);//a-b=c
    	
    	aa(c);//删除c的前导0
    	
    	for(int i=c[0];i>=1;i--)
    	{
    		cout<<c[i];//输出每一位	
    	} 
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    高精度乘法:

    #include
    
    using namespace std; 
    
    int a[1000],b[1000],c[1000]; 
    
    void init1(int a[])
    {
    	char s[1000];//通过字符数组的形式输入数字 
    	
    	gets(s);
    	
    	a[0]=strlen(s);//a[0]保存字符数组s的位数 
    	
    	for(int i=1;i<=a[0];i++)
    	{
    		a[i]=s[a[0]-i]-'0';//将字符数组转换为整形数组,并逆序储存 
    	}
    }
    
    void init2(int a[])
    {
    	string s;//通过字符串的形式输入数字 
    	
    	getline(cin,s);//或cin>>s; 
    	
    	a[0]=s.size();//a[0]保存字符串s的位数 或s.length(); 
    	
    	for(int i=1;i<=a[0];i++)
    	{
    		a[i]=s[a[0]-i]-'0';//将字符串转换为整形数组,并逆序储存 
    	}
    }
    
    void chengfa(int a[],int b[],int c[])
    {
    	for(int i=1;i<=b[0];i++)
    	{
    		int x=0;//暂存进位,开始为0 
    		
    		for(int j=1;j<=a[0];j++)
    		{
    			c[i+j-1]=c[i+j-1]+x+b[i]*a[j];//原数+上一次进的位数+当前的乘积 
    			
    			x=c[i+j-1]/10;//进位 
    			
    			c[i+j-1]%=10;//进位后的结果 
    		}
    		
    		c[a[0]+i]=x;//每次向前进一位 
    	}
    	
    	c[0]=a[0]+b[0];//乘积c最多的位数 
    }
    
    void aa(int a[])//删除数组a的前导0 
    {
    	while(a[0]>=1&&a[a[0]]==0)
    	{
    		a[0]--;	
    	}	
    } 
    
    int main()
    {
    	init1(a);
    	init1(b);//输入	
    	
    	chengfa(a,b,c);//a*b=c
    	
    	aa(c);//删除c的前导0
    	
    	for(int i=c[0];i>=1;i--)
    	{
    		cout<<c[i];//输出每一位	
    	} 
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    高精度除法:

    高精除以低精:

    #include
    
    using namespace std; 
    
    int a[1000],b[1000],c[1000]; 
    
    //int b; 
    
    void init1(int a[])
    {
    	char s[1000];//通过字符数组的形式输入数字 
    	
    	gets(s);
    	
    	a[0]=strlen(s);//a[0]保存字符数组s的位数 
    	
    	for(int i=1;i<=a[0];i++)
    	{
    		a[i]=s[a[0]-i]-'0';//将字符数组转换为整形数组,并逆序储存 
    	}
    }
    
    void init2(int a[])
    {
    	string s;//通过字符串的形式输入数字 
    	
    	getline(cin,s);//或cin>>s; 
    	
    	a[0]=s.size();//a[0]保存字符串s的位数 或s.length(); 
    	
    	for(int i=1;i<=a[0];i++)
    	{
    		a[i]=s[a[0]-i]-'0';//将字符串转换为整形数组,并逆序储存 
    	}
    }
    
    void chudi(int a[],int b,int c[])
    {
    	int t=0;
    	
    	int x=0;//余数
    	
    	for(int i=1;i<=a[0];i++)//模拟除法 
    	{
    		t=x*10+a[i];
    		
    		c[i]=t/b;//商 
    		
    		x=t%b;//每次相除后的余数	
    	} 
    }
    
    int main()
    {
    	init1(a);
    	cin>>b;//输入
    	
    	chudi(a,b,c);//a/b=c
    	
    	int k=1;//商的下标 
    	
    	while(c[k]==0&&k<=a[0])
    	{
    		k++;//删除前导0 
    	} 
    	
    	for(int i=k;i<=a[0];i++)
    	{
    		cout<<c[i];//输出每一位 
    	}
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    高精除以高精:

    #include
    
    using namespace std; 
    
    int a[1000],b[1000],c[1000]; 
    
    int B;//为除以低精 
    
    void init1(int a[])
    {
    	char s[1000];//通过字符数组的形式输入数字 
    	
    	gets(s);
    	
    	a[0]=strlen(s);//a[0]保存字符数组s的位数 
    	
    	for(int i=1;i<=a[0];i++)
    	{
    		a[i]=s[a[0]-i]-'0';//将字符数组转换为整形数组,并逆序储存 
    	}
    }
    
    void init2(int a[])
    {
    	string s;//通过字符串的形式输入数字 
    	
    	getline(cin,s);//或cin>>s; 
    	
    	a[0]=s.size();//a[0]保存字符串s的位数 或s.length(); 
    	
    	for(int i=1;i<=a[0];i++)
    	{
    		a[i]=s[a[0]-i]-'0';//将字符串转换为整形数组,并逆序储存 
    	}
    }
    
    int com(int a[],int b[])//比较a,b;若a>b为1;若a
    {
    	if(a[0]>b[0])
    	{
    		return 1;
    	}
    	else
    	{
    		if(a[0]<b[0])
    		{
    			return -1;
    		}
    		else
    		{
    			if(a[0]==b[0])
    			{
    				for(int i=a[0];i>0;i--)
    				{
    					if(a[i]>b[i])
    					{
    						return 1;
    					}
    					
    					if(a[i]<b[i])
    					{
    						return -1;	
    					} 
    					
    					if(a[i]==b[i])
    					{
    						continue;
    					}
    				}
    			}
    		}
    	}
    	
    	return 0;
    } 
    
    void jian2(int a[],int b[])//计算a=a-b 
    {
    	int flag=com(a,b);
    	
    	if(flag==0)//a=b
    	{
    		a[0]=0;
    		
    		return ;
    	}
    	
    	if(flag==1)//a>b
    	{
    		for(int i=1;i<=a[0];i++)//模拟减法 
    		{
    			if(a[i]<b[i])//若不够减 
    			{
    				a[i+1]--;//向上借一位 
    				
    				a[i]+=10;
    			}
    			
    			a[i]-=b[i];
    		}
    		
    		while(a[0]>0&&a[a[0]]==0)//删除前导0 
    		{
    			a[0]--;
    		}
    		
    		return ;
    	}
    }
    
    void chugao(int a[],int b[],int c[])//高精除高精 
    {
    	int t[1000];
    	
    	c[0]=a[0]-b[0]+1;//商最多的位数
    	
    	for(int i=c[0];i>0;i--)//模拟除法 
    	{
    		memset(t,0,sizeof(t));//每次清空
    		
    		for(int j=1;j<=b[0];j++)//把数组b复制给t 
    		{
    			t[i+j-1]=b[j];//下标右偏移i-1位 
    		} 
    		
    		t[0]=b[0]+i-1;//位数
    		
    		while(com(a,t)>=0)
    		{
    			c[i]++;//商加1 
    			
    			jian2(a,t);//模拟减法(a=a-t) 
    		} 
    	} 
    }
    
    void print(int a[])
    {
    	while(a[0]>0&&a[a[0]]==0)//删除前导0 
    	{
    	 	a[0]--;//位数-1 
    	}
    		
    	if(a[0]==0)//结果为0 
    	{
    		cout<<0<<endl;
    	}
    	else//结果不为0 
    	{
    		for(int i=a[0];i>=1;i--)
    		{
    			cout<<a[i];
    		}
    			
    		cout<<endl;
    	}
    } 
    
    int main()
    {
    	init1(a);
    	init1(b);//输入
    	
    	chugao(a,b,c);
    	
    	print(c);//输出商
    	print(a);//输出余数
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168

    高精度四则运算完整代码(含进位借位):

    #include
    
    using namespace std; 
    
    int a[1000],b[1000],c[1000]; 
    
    int B;//为除以低精 
    
    void init1(int a[])
    {
    	char s[1000];//通过字符数组的形式输入数字 
    	
    	gets(s);
    	
    	a[0]=strlen(s);//a[0]保存字符数组s的位数 
    	
    	for(int i=1;i<=a[0];i++)
    	{
    		a[i]=s[a[0]-i]-'0';//将字符数组转换为整形数组,并逆序储存 
    	}
    }
    
    void init2(int a[])
    {
    	string s;//通过字符串的形式输入数字 
    	
    	getline(cin,s);//或cin>>s; 
    	
    	a[0]=s.size();//a[0]保存字符串s的位数 或s.length(); 
    	
    	for(int i=1;i<=a[0];i++)
    	{
    		a[i]=s[a[0]-i]-'0';//将字符串转换为整形数组,并逆序储存 
    	}
    }
    
    /*void jia()
    {
    	c[i]=a[i]+b[i];//对应位相加 
    	
    	if(c[i]>=10)//进位了(和大于10) 
    	{
    		c[i+1]++;//向前进一位 
    		
    		c[i]%=10;//进位后剩下的数字 
    	}
    }*/
    
    /*void jian()
    {
    	if(a[i]
    
    /*void cheng()
    {
    	c[i+j-1]=a[i]*b[j]+x+c[i+j-1];//对应位的值 
    	
    	x=c[i+j-1]/10;//进位数 
    	
    	c[i+j-1]%=10;//进位后剩下的数字 
    }*/
    
    void chengfa(int a[],int b[],int c[])
    {
    	for(int i=1;i<=b[0];i++)
    	{
    		int x=0;//暂存进位,开始为0 
    		
    		for(int j=1;j<=a[0];j++)
    		{
    			c[i+j-1]=c[i+j-1]+x+b[i]*a[j];//原数+上一次进的位数+当前的乘积 
    			
    			x=c[i+j-1]/10;//进位 
    			
    			c[i+j-1]%=10;//进位后的结果 
    		}
    		
    		c[a[0]+i]=x;//每次向前进一位 
    	}
    	
    	c[0]=a[0]+b[0];//乘积c最多的位数 
    }
    
    void chudi(int a[],int b,int c[])
    {
    	int t=0;
    	
    	int x=0;//余数
    	
    	for(int i=1;i<=a[0];i++)//模拟除法 
    	{
    		t=x*10+a[i];
    		
    		c[i]=t/b;//商 
    		
    		x=t%b;//每次相除后的余数	
    	} 
    }
    
    void jiafa(int a[],int b[],int c[])
    {
    	int x=0;//暂存进位,从0开始  
    	int i=1;//位数的下标 
    	
    	while(i<=a[0]||i<=b[0])
    	{
    		c[i]=a[i]+b[i]+x;//对应位相加+上一次的位数 
    		
    		x=c[i]/10;//进位 
    		
    		c[i]=c[i]%10;//进位后剩下的数字 
    		
    		i++;//模拟下一位 
    	}
    	
    	c[i]=x;//最后的位数 
    	c[0]=i;//将和c的位数统一保存在c[0]中 
    }
    
    void jianfa(int a[],int b[],int c[])
    {
    	int i=1;//位数的下标 
    	
    	while(i<=a[0])
    	{
    		if(a[i]<b[i])
    		{
    			a[i+1]--;//借位 
    			
    			a[i]+=10;
    		}
    		
    		c[i]=a[i]-b[i];
    		
    		i++;
    	}
    	
    	c[0]=i;//将差c的位数保存在c[0]中 
    }
    
    int com(int a[],int b[])//比较a,b;若a>b为1;若a
    {
    	if(a[0]>b[0])
    	{
    		return 1;
    	}
    	else
    	{
    		if(a[0]<b[0])
    		{
    			return -1;
    		}
    		else
    		{
    			if(a[0]==b[0])
    			{
    				for(int i=a[0];i>0;i--)
    				{
    					if(a[i]>b[i])
    					{
    						return 1;
    					}
    					
    					if(a[i]<b[i])
    					{
    						return -1;	
    					} 
    					
    					if(a[i]==b[i])
    					{
    						continue;
    					}
    				}
    			}
    		}
    	}
    	
    	return 0;
    } 
    
    void jian2(int a[],int b[])//计算a=a-b 
    {
    	int flag=com(a,b);
    	
    	if(flag==0)//a=b
    	{
    		a[0]=0;
    		
    		return ;
    	}
    	
    	if(flag==1)//a>b
    	{
    		for(int i=1;i<=a[0];i++)//模拟减法 
    		{
    			if(a[i]<b[i])//若不够减 
    			{
    				a[i+1]--;//向上借一位 
    				
    				a[i]+=10;
    			}
    			
    			a[i]-=b[i];
    		}
    		
    		while(a[0]>0&&a[a[0]]==0)//删除前导0 
    		{
    			a[0]--;
    		}
    		
    		return ;
    	}
    }
    
    void chugao(int a[],int b[],int c[])//高精除高精 
    {
    	int t[1000];
    	
    	c[0]=a[0]-b[0]+1;//商最多的位数
    	
    	for(int i=c[0];i>0;i--)//模拟除法 
    	{
    		memset(t,0,sizeof(t));//每次清空
    		
    		for(int j=1;j<=b[0];j++)//把数组b复制给t 
    		{
    			t[i+j-1]=b[j];//下标右偏移i-1位 
    		} 
    		
    		t[0]=b[0]+i-1;//位数
    		
    		while(com(a,t)>=0)
    		{
    			c[i]++;//商加1 
    			
    			jian2(a,t);//模拟减法(a=a-t) 
    		} 
    	} 
    }
    
    void aa(int a[])//删除数组a的前导0 
    {
    	while(a[0]>=1&&a[a[0]]==0)
    	{
    		a[0]--;	
    	}	
    } 
    
    void print(int a[])
    {
    	while(a[0]>0&&a[a[0]]==0)//删除前导0 
    	{
    	 	a[0]--;//位数-1 
    	}
    		
    	if(a[0]==0)//结果为0 
    	{
    		cout<<0<<endl;
    	}
    	else//结果不为0 
    	{
    		for(int i=a[0];i>=1;i--)
    		{
    			cout<<a[i];
    		}
    			
    		cout<<endl;
    	}
    } 
    
    int main()
    {
    	//------------加法-------------- 
    	init1(a);
    	init1(b);//输入	
    	
    	aa(a);
    	aa(b);//删除前导0
    	
    	jiafa(a,b,c);//a+b=c
    	
    	aa(c);//删除c的前导0
    	
    	for(int i=c[0];i>=1;i--)
    	{
    		cout<<c[i];//输出每一位	
    	} 
    	
    	//------------减法-------------- 
    	init1(a);
    	init1(b);//输入
    	
    	jianfa(a,b,c);//a-b=c
    	
    	aa(c);//删除c的前导0
    	
    	for(int i=c[0];i>=1;i--)
    	{
    		cout<<c[i];//输出每一位	
    	} 
    	
    	//------------乘法-------------- 
    	init1(a);
    	init1(b);//输入	
    	
    	chengfa(a,b,c);//a*b=c
    	
    	aa(c);//删除c的前导0
    	
    	for(int i=c[0];i>=1;i--)
    	{
    		cout<<c[i];//输出每一位	
    	} 
    	
    	//------------高精除以低精-------------- 
    	init1(a);
    	cin>>B;//输入
    	
    	chudi(a,B,c);//a/b=c
    	
    	int k=1;//商的下标 
    	
    	while(c[k]==0&&k<=a[0])
    	{
    		k++;//删除前导0 
    	} 
    	
    	for(int i=k;i<=a[0];i++)
    	{
    		cout<<c[i];//输出每一位 
    	}
    	
    	//------------高精除以高精--------------
    	init1(a);
    	init1(b);//输入
    	
    	chugao(a,b,c);
    	
    	print(c);//输出商
    	print(a);//输出余数
    	
    	return 0; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350

    高精度经典例题

    [NOIP1998 普及组] 阶乘之和

    题目描述

    用高精度计算出 S = 1 ! + 2 ! + 3 ! + ⋯ + n ! S = 1! + 2! + 3! + \cdots + n! S=1!+2!+3!++n! n ≤ 50 n \le 50 n50)。

    其中 ! 表示阶乘,定义为 n ! = n × ( n − 1 ) × ( n − 2 ) × ⋯ × 1 n!=n\times (n-1)\times (n-2)\times \cdots \times 1 n!=n×(n1)×(n2)××1。例如, 5 ! = 5 × 4 × 3 × 2 × 1 = 120 5! = 5 \times 4 \times 3 \times 2 \times 1=120 5!=5×4×3×2×1=120

    输入格式

    一个正整数 n n n

    输出格式

    一个正整数 S S S,表示计算结果。

    样例输入 #1
    3
    
    • 1
    样例输出 #1
    9
    
    • 1
    提示

    【数据范围】

    对于 100 % 100 \% 100% 的数据, 1 ≤ n ≤ 50 1 \le n \le 50 1n50

    分析

    该题是一道简单的高精度乘法与高精度加法的模板题,我们只需套进去就行了。

    例题代码
    #include
    
    using namespace std; 
    
    int n,a[1000],s[1000];
    
    void cheng(int s)//高精度乘法 
    {
    	int x=0;
    	
    	for(int i=100;i>=0;i--)
    	{
    		a[i]=a[i]*s+x;
    		
    		x=a[i]/10;
    		
    		a[i]=a[i]%10;
    	}
    }
    
    void jia()//高精度加法
    {
    	int x=0;
    	
    	for(int i=100;i>=0;i--)
    	{
    		s[i]=s[i]+a[i]+x;
    		
    		x=s[i]/10;
    		
    		s[i]=s[i]%10;
    	}
    }
    
    int main()
    {
    	cin>>n;
    	
    	s[100]=a[100]=1;
    	
    	for(int i=2;i<=n;i++)//求阶乘 
    	{
    		cheng(i);
    		
    		jia();
    	}
    	
    	int K;
    	
    	for(int i=0;i<=100;i++)
    	{
    		if(s[i]!=0)
    		{
    			K=i;
    			
    			break;
    		}
    	}
    	
    	for(int i=K;i<=100;i++)
    	{ 
    	   cout<<s[i];
    	} 
    	   
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    文章没有更多内容啦~~~

  • 相关阅读:
    std::shared_ptr(基础、仿写、安全性)
    PHP日志库 - Monolog 知识整理
    Hbase解决ERROR: KeeperErrorCode = ConnectionLoss for /hbase/master报错
    计算机毕业设计Python+django网上咖啡商城(源码+系统+mysql数据库+Lw文档)
    白话模电:3.三极管(考研面试与笔试常考问题)
    Servlet
    注解用法含义
    第2章 变量和基本类型读书笔记
    深度学习pytorch之hub模块
    ubuntu 软件包管理之一
  • 原文地址:https://blog.csdn.net/m0_66603329/article/details/126904138