1. 程式人生 > >大樹乘法(C/C++實現)

大樹乘法(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()