高精度整数加法

问题描述: 
在计算机中,由于处理器位宽限制,只能处理有限精度的十进制整数加减法,比如在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);
 }
}

 

以上仅是我个人的一点想法,方法可能不是很好,希望大家指导!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值