高精度整數加法

問題描述: 
在計算機中,由於處理器位寬限制,只能處理有限精度的十進制整數加減法,比如在32位寬處理器計算機中,

參與運算的操作數和結果必須在-231~231-1之間。如果需要進行更大範圍的十進制整數加法,需要使用特殊

的方式實現,比如使用字符串保存操作數和結果,採取逐位運算的方式。

 

如下: 

9876543210 + 1234567890 = ?

讓字符串 num1="9876543210",字符串 num2="1234567890",結果保存在字符串 result = "11111111100"

 

-9876543210 + (-1234567890) = ?

讓字符串 num1="-9876543210",字符串 num2="-1234567890",結果保存在字符串 result = "-11111111100"

 

題目:要求編程實現上述高精度的十進制加法。

 

 

我的思路是:先將每個字符串除符號位之外的所有數字位轉換成整數,然後按照右對齊的方式,暫時不考慮進位或借位,進行加減法運算,之後再考慮每一位是否需要進位或借位,更新每一位的值,最後再將這些數值轉換成字符,存入相應的數組。

 

下面是參考代碼:

#include <iostream>
#include <stdlib.h>
#include <string>
#define MAX 15
using namespace std;

void add(const char *num1,const char *num2,char *result);

int main()
{
 char num1[]="-9876543210";
 char num2[]="-1234567890";
 char res[MAX]="";

 add(num1,num2,res);                                                                                                                                          
 return 0;
}

void add(const char *num1,const char *num2,char *result)
{
 if (num1==NULL || num2==NULL)
 {
  return;
 }
 if ((num1[0]=='-'&& num1[1]=='0') || num1[0]=='0' || (num2[0]=='-'&& num2[1]=='0') || num2[0]=='0')
 {
  return;
 }
 const char *n1=NULL;
 const char *n2=NULL;
 char *p=result;

 int len1=strlen(num1);
 int len2=strlen(num2);
 int sum[MAX+1]={0};
 int x[MAX]={0};
 int y[MAX]={0};

 int i=0,j=0;
 //不考慮符號位,哪個字符串長,就將哪個賦給n1,將來轉換成整數時存放在x[]中
 if((*num1=='-' && *num2=='-') || (*num1!='-' && *num2!='-'))
 {
  if (len1>=len2)
  {
   n1=num1;
   n2=num2;
  }
  else
  {
   n1=num2;
   n2=num1;
  }
 }
 else if(*num1=='-' && *num2!='-')
 {
  if (len1-1>=len2)
  {
   n1=num1;
   n2=num2;
  }
  else
  {
   n1=num2;
   n2=num1;
  }
 }
 else
 {
  if (len1>=len2-1)
  {
   n1=num1;
   n2=num2;
  }
  else
  {
   n1=num2;
   n2=num1;
  }
 }
 //把第一個數的每一位轉換成數字,保存在數組中
 if (n1[0]!='-')
 {
  for (i=len1-1;i>=0;i--)
  {
   x[i]=(n1[i]-'0');
   //cout <<x[i]<<" ";
  }
 }
 else
 {
  for (i=len1-1;i>0;i--)
  {
   x[i]=n1[i]-'0';
   //cout <<x[i]<<" ";
  }
 }


 //把第二個數的每一位轉換成數字,保存在數組中
 if (*n2!='-')
 {
  for (j=len2-1;j>=0;j--)
  {
   y[j]=n2[j]-'0';
   //cout <<y[j]<<" ";
  }
 }
 else
 {
  for (j=len2-1;j>0;j--)
  {
   y[j]=n2[j]-'0';
   //cout <<y[j]<<" ";
  }
 }
//cout<<endl;
 int takeover=0;//進位標誌符
 int takedown=0;//借位標誌符
 int k=0;

 //1:兩個數都爲正數
 if (*n1!='-' && *n2!='-')
 {
  //先不考慮進位,求每一位對應的和
   for(i=len1-1,j=len2-1;i>=0;i--,j--)
   {
    if (j>=0)
    {
     sum[k]=x[i]+y[j];
     //cout <<sum[k] <<" ";
    }
    else
    {
     sum[k]=x[i];
    }
    k++;
   }
   //cout<<endl;

   //計算進位,修改相應位的值
   for (i=0;i<MAX;i++)
   {
    if (sum[i]>=10)
    {
     sum[i]=sum[i]%10;
     takeover=1;
     sum[i+1]+=takeover;
    }
   }

   //把每一位轉換成字符型
   if (sum[len1]==0)
   {
    for (i=0;i<len1;i++)
    {
     p[len1-1-i]=sum[i]+'0';
    }
   }
   else
   {
    for (i=0;i<=len1;i++)
    {
     p[len1-i]=sum[i]+'0';
    }
   }
   printf("%s\n",p);
      
 }
 //2:兩個數都爲負數
 else if (*n1=='-' && *n2=='-')
 {
  //先不考慮進位,求每一位對應的和
  for(i=len1-1,j=len2-1;i>0;i--,j--)
  {
   if (j>0)
   {
    sum[k]=x[i]+y[j];
    //cout <<sum[k] <<" ";
   }
   else
   {
    sum[k]=x[i];
   }
   k++;
  }
  //cout<<endl;
  
  //計算進位,修改相應位的值
  for (i=0;i<MAX;i++)
  {
   if (sum[i]>=10)
   {
    sum[i]=sum[i]%10;
    takeover=1;
    sum[i+1]+=takeover;
   }
  }
  
  //把每一位轉換成字符型
  if (sum[len1-1]==0)
  {
   for (i=0;i<len1-1;i++)
   {
    p[len1-1-i]=sum[i]+'0';
   }
  }
  else
  {
   for (i=0;i<len1;i++)
   {
    p[len1-i]=sum[i]+'0';
   }
  }
  p[0]='-';
   printf("%s\n",p);
 }
 //3:較長的數爲正數,較短的數爲負數
 else if (*n1!='-' && *n2=='-')
 {
  //不考慮借位,計算每一位對應的差
  for(i=len1-1,j=len2-1;i>=0;i--,j--)
  {
   if (j>0)
   {
    sum[k]=x[i]-y[j];
   }
   else
   {
    sum[k]=x[i];
   }
   k++;
  }

  //根據每一位的值,考慮借位,更新數值
   for (i=0;i<len1-1;i++)
   {
    if (sum[i]<0)
    {
     sum[i]=sum[i]+10;
     takedown=1;
     sum[i+1]-=takedown;
    }
   }
   //把每一位轉換成字符型
   if (sum[len1-1]>0)
   {
    for (i=0;i<len1;i++)
    {
     p[len1-1-i]=sum[i]+'0';
    }
   }
   else if(sum[len1-1]==0)
   {
    for (i=0;i<len1-1;i++)
    {
     p[len1-2-i]=sum[i]+'0';
    }
   }
   else
   {
    for (i=0;i<len1-1;i++)
    {
     sum[i]=10-sum[i];
     takedown=1;
     sum[i+1]+=takedown;
    }
    if(sum[i]==0)
    {
     for(i=0;i<len1-1;i++)
     {
      p[len1-1-i]=sum[i]+'0';
     }
    }
    else if (sum[i]<0)
    {
     sum[i]=-sum[i];
     for(i=0;i<=len1-1;i++)
     {
      p[len1-i]=sum[i]+'0';
     }
    }
    p[0]='-';
   } 

 printf("%s\n",p);
 }
 //4:較長的數爲負數,較短的數爲正數
 else if (*n1=='-' && *n2!='-')
 {
  //不考慮借位,計算每一位對應的差
  for(i=len1-1,j=len2-1;i>0;i--,j--)
  {
   if (j>=0)
   {
    sum[k]=x[i]-y[j];
   }
   else
   {
    sum[k]=x[i];
   }
   k++;
  }

   //根據每一位的值,考慮借位,更新數值
   for (i=0;i<len1-2;i++)
   {
    if (sum[i]<0)
    {
     sum[i]=sum[i]+10;
     takedown=1;
     sum[i+1]-=takedown;
    }
   }
   //把每一位轉換成字符型
   if (sum[len1-2]>0)
   {
    for (i=0;i<len1-1;i++)
    {
     p[len1-1-i]=sum[i]+'0';
    }
    p[0]='-';
   }
   else if(sum[len1-2]==0)
   {
    for (i=0;i<len1-2;i++)
    {
     p[len1-2-i]=sum[i]+'0';
    }
    p[0]='-';
   }
   else
   {
    for (i=0;i<len1-2;i++)
    {
     sum[i]=10-sum[i];
     takedown=1;
     sum[i+1]+=takedown;
    }
    if(sum[i]==0)
    {
     for(i=0;i<len1-1;i++)
     {
      p[len1-2-i]=sum[i]+'0';
     }
     p[0]='-';
    }
    else if (sum[i]<0)
    {
     sum[i]=-sum[i];
     for(i=0;i<=len1-2;i++)
     {
      p[len1-2-i]=sum[i]+'0';
     }
    }
   }  
 printf("%s\n",p);
 }
}

 

以上僅是我個人的一點想法,方法可能不是很好,希望大家指導!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章