大树乘法(C/C++实现)

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include <string.h>  //strlen(x)必要,而不是<string> 
using namespace std; 
int main()
{
    char x[99999];
	char y[99999];
	char z[99999];//存放每次乘法结果
	char z_all[99999]; //存放加起来的结果  
	char big[99999];//存放x[]和y[]更大的那个数组 ,相当于列式计算的上面那个数 
	char small[99999];//存放x[]和y[]更小的那个数组 ,相当于列式计算的下面那个数 
	
	int multi=0;//2个数相乘得到的 
    int count=0;//乘法进位的数
    
	int length=0;//用于计算z[]的长度
	int length_all=0; //用于计算z_all[]的长度,很难搞,因为ascii0代表为\0,所以strlen(z_all)没用,length_all=length或者length+1或-1 
	
    int plus=0;//2个数相加得到的 
	int count_z=0;//加法进位的数
	 
    scanf("%s",&x);
    scanf("%s",&y);
    
    int x_length=strlen(x);
    int big_length=0;//记录x_length和y_length更大的长度为 
    
    int y_length=strlen(y);
    int small_length=0;//记录x_length和y_length更小的长度为 
    
    //1,判断x[]和y[]谁更长,得到长度,并把更长的放入big[],更短的放入small[] 
	//2,每一位都-48,才可以开始计算。 
	if(x_length>y_length)
    {
    	big_length=x_length;
    	small_length=y_length;
    	for(int i=0;i<(big_length);i++)
    	{
    		big[i]=x[i]-48;
    	    if(i<y_length)
   	 		    small[i]=y[i]-48;
   		 	else small[i]=0;
   	    }
    } 	 
    else 
    {
    	big_length=y_length;
    	small_length=x_length;
    	for(int i=0;i<(big_length);i++)
    	{
    		big[i]=y[i]-48;
    	    if(i<x_length)
   	 		    small[i]=x[i]-48;
   		 	else small[i]=0;
   	    }
    }	
	
	//字符串逆转strrev(),不能用这个函数,和strlen()一样,碰ascii0结束 
	//strrev(big);
	int num=big_length/2;
	int first_num=0;//执行字符串逆转的 
	for(int i=0;i<num;i++)
    {
    	first_num=big[i];
    	big[i]=big[big_length-1-i];
    	big[big_length-1-i]=first_num;
    }
	
	//strrev(small);
	num=small_length/2;
	for(int i=0;i<num;i++)
    {
    	first_num=small[i];
    	small[i]=small[small_length-1-i];
    	small[small_length-1-i]=first_num;
    }
	
	//--------------------计算每次结果,并执行加法,得到总结果 
	for(int i=0;i<small_length;i++)
	{
		memset(z, 0, sizeof(z));//用完数组一定要记得情空 
		count=0;
		length=0;
		for(int j=0;j<big_length;j++)
	    {
	    	
		    multi=small[i]*big[j]+count;
		    if(multi<10)
		    {
		    	count=0;
			}
			else count=multi/10; 
			 
		    z[j]=multi%10;
		    length++;
		    
		    //每次运算结果的第一位可能需要进位 
		    if(j==big_length-1)
		    {
		    	if(multi>=10)
		    	{
		    		length++;
		    		z[j+1]=multi/10;
		    		
				}
			    count=0;     //运算完了之后进位为0
			    
			}    
            
	    }
	    
	    //逆转每次运算结果再加上根据正在计算small[]中第几个数决定末尾的0,真正的每次运算结果 
	    //strrev(z);//字符串逆转 
		num=length/2;
	    for(int m=0;m<num;m++)
        {
    		first_num=z[m];
    		z[m]=z[length-1-m];
    		z[length-1-m]=first_num;
    	}
		//根据正在计算small[]中第几个数决定末尾的0,真正的每次运算结果
		for(int m=0;m<i;m++)
	    {
	    	z[length]=0;
	    	length++;
		}
		
		//在每次 执行z_all[]和z[] 的加法  之前先对z_all[]补充到和z[]一样的位数
	    //可能补充1位,可能补充2位 
		if(length_all==length)
		;
		else 
		{
			//1 是 -1,2是+0,3是+1 ,4是 +2,相差2 
			//观察得到 length-length_all-2 是 
			for(int m=length+(length-length_all-2);m>=length-length_all;m--)
	    	{
	    		z_all[m]=z_all[m-(length-length_all)];
			}
			for(int m=0;m<length-length_all;m++)
			{
				z_all[m]=0;
			}
			length_all=length;
		
		}	
				
		//加起来存放在z_all[],执行z_all[]和z[] 的加法
		for(int m=(length-1);m>=0;m--)
		{
		    plus=z[m]+z_all[m]+count_z;
			if(plus>=10)
			{
				count_z=1;
				z_all[m]=plus%10;
				
				//每次运算结果的第一位可能需要进位
				if(m==0)
				{
					count_z=0;

					//必须这样写,不然strlen()以\0结束,而ascii的0就是\0  
					length_all=length+1;
					for(int n=length;n>0;n--) 
					{
						z_all[n]=z_all[n-1];
					}
					z_all[0]=1;
					
				} 
				    
			}
			else 
			{
				z_all[m]=plus;
				count_z=0;
			}
	    }
	    
	}
	//--------------------得到总结果
	
	//还原成char[],才可以用字符串%s显示出来,不然可能要一个一个%d输出	 
    for(int i=0;i<length_all;i++)
    {
    	z_all[i]+=48;
	}
    
    printf("总结果为%s",z_all);
    system("pause");
 } 

190行的代码,测试用例
99999
888
答案是88799112

456456
123
答案是56144088

测试输入的2个大数含有0,导致z_all[]有0,z[]有0
5002
1005
答案是5027010

测试先输入的数更小
5153135
561523152315615615614
答案是2893604609507929875367049890

执行加法的时候,z_all[]肯定小于等于z[]的位数,但是可能相差2位
测试z_all[]和z[]相差2位会不会出错
890749640310
50438001
答案44927631248705420310

测试很大的数
90651132051212022320006511320512120223200132051212022313205121202232000651132051212013205121202232000651132051212013205121202232000651132051212013205121202232000651132051212020006511320512121320512120223200065113205121200223200065113205121201320512120132051212022320006511320512120132051212022320006511320512120
90651132051212022320006511320512120223200132051212022313205121202232000651132051212013205121202232000651132051212013205121202232000651132051212013205121202232000651132051212020006511320512121320512120223200065113205121200223200065113205121201320512120132051212022320006511320512120132051212022320006511320512120

答案是
8217627742166279593258384227255322134089168057783095489827406231962126915594425136982130897336827272053686532782672814722755608909707178267744737424004508273738713256092706803266393688426607267974586188598208659424356181871486133193036707046839862429341995222708292917387307560071705279510878182313569177763680001920799585684429461042518936481023593237602722809931476763334431426660612680265603460144823480818435663628168450038546990715014132411802891692469338365699322791894396940981129039967003179268156321618886806960655095730601018201634939432173224868109964974975399259786821141967502182478768938331611554659066894400

1,strlen()和strrev()不能对char[]存放数字0进行操作,因为ascii0就是字符\0,需要自己实现strlen()和strrev()

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值