葡萄成熟时 发表于 2014-3-2 16:13:48

大数加减我的做法

大数加减算法给大家分享,这程序可以算很大的数还有很长的精度,我测了没发现有问题,如果大家发现问题麻烦告诉一声。

首先把0+0这种特殊情况处理掉;
然后,两个数的正负分为 同正、同负、一正一负三类(即使是0也当正数处理);
然后,这又三类分为:两个数都没有小数、至少一个有小数点,前者两个数都不用补0,后者要补0和小数点;
加法算法:两个数按小数点对齐,按位相加取余数,取整保存进位(留给下一位)。
               5 3 8 8 . 4 5 6 0
             +       1 2 . 7 8 0 0             =   5 4 0 1 . 2 3 6 0
减法算法:两个数按小数点对齐,按位相减,如果被减数>=减数则直接直接保留相减的结果;如果被减数<减数,向前借1(一直找到不是0的借),保留相减再加10的结果。
               5 3 8 8 . 4 5 6 0
            -      1 2 . 7 8 0 0            =5 3 7 5 . 6 7 6 0

葡萄成熟时 发表于 2014-3-2 16:25:11


#include <iostream>
#include <string>
using namespace std;
//加法
void Plus(string a, string b, string &result)
{
    string::size_type i, j, k;
    int temp=0;//存放进位
    //同为相加取余,temp保存进位
    for(i=a.length()-1, j=b.length()-1, k=result.length()-1;i!=0 && j!=0 && k!=0;--i,--j,--k)
    {
      if(a == '.')//'.'号不计算
      {
            result = '.';
            continue;
      }
      else//不是'.'号就计算
      {
            temp += a - '0' + b - '0';
            result = temp % 10 + 48;
            temp /= 10;
      }
    }

    for(; i!=0; --i,--k)//a可能还有数字
    {
      temp += a - '0';
      result = temp % 10 + 48;
      temp /= 10;
    }
    if(temp > 0)//最后一个进位
      result = temp + 48;
}
//减法
void Minus(string a, string b, string &result)
{
    string::size_type i, j, k, t;

    for(i=a.length()-1, j=b.length()-1, k=result.length()-1;i!=0 && j!=0 && k!=0;--i,--j,--k)
    {
      if(a >= b)
      {
            if(a == '.')//'.'号不计算
            {
                result = '.';
                continue;
            }
            result = a - b + 48;
      }
      else//向前借1
      {
            result = a - b + 10 + 48;
            t = i - 1;
            while(a=='0' || a =='.')//找到第一个不是0的数
            {
                if(a == '0')
                  a = '9';//0直接变成9
                --t;
            }
            a -= 1;//找到了第一个不是0的数,减一
      }
    }
    while(i !=0 )//a可能还有数
    {
      result = a;
      --i;
      --k;
    }
}
//处理有或没有小数点的情况,function用来标识是做加法还是做减法
void AddZero(int function, string a, string b, string &result)
{
    string::size_type aIndex, bIndex, t; //a和b的小数点号位置
    unsined dif, aRight, bRight;//a,b小数位数差,a的小数位数,b的小数位数
    bool resultIsNegative = false;//判断结果是否是负的
   
    result.append(a.length() + b.length(), '0');//给result负初值
    a.insert(a.begin(), '0');//在a前面添加0
    b.insert(b.begin(), '0');
    aIndex = a.find_first_of('.');//获取a的小数点号位置
    bIndex = b.find_first_of('.');//获取b的小数点号位置

    if(aIndex!=string::npos && bIndex!=string::npos)//a,b都有小数点
    {

      aRight = a.length() - aIndex - 1;//a的小数位数
      bRight = b.length() - bIndex - 1;//b的小数位数
      if(aRight > bRight)
      {
            dif = aRight - bRight;//a,b小数位数差
            b.append(dif, '0');//在b末尾添加dif个0,跟a的小数位数相等,方便计算
      }
      else if(aRight < bRight)
      {
            dif = bRight - aRight;//a,b小数位数差
            a.append(dif, '0');//在a末尾添加dif个0,跟b的小数位数相等,方便计算
      }
    }
    else if(aIndex!=string::npos && bIndex==string::npos)//a有小数点,b没有
    {
      aRight = a.length() - aIndex - 1;//a的小数位数
      b.append(1, '.');//在b末尾添加.号
      b.append(aRight, '0');//在b末尾添加aRight个0
    }
    else if(aIndex==string::npos && bIndex!=string::npos)//b有小数点,a没有
    {
      bRight = b.length() - bIndex - 1;//b的小数点位数
      a.append(1, '.');//在b末尾添加.号
      a.append(bRight, '0');//在a末尾添加bRight个0
    }

    if(function == 0)
    {
      if(a.length() < b.length())
      {
            a.swap(b);//保证a.length()>=b.length()
      }
      Plus(a, b, result);//加
      while(*result.begin() == '0')
      {
            result.erase(result.begin());//清除前面的0
      }
      //补回.号前面的0,因为0.2155+0.544这种情况会把'.'号前面的0删除除
      if(aIndex!=string::npos || bIndex!=string::npos)
      {
            t = result.find_first_of('.');
            if(t == 0)
                result.insert(result.begin(), '0');
      }
    }
    else
    {
      if(a.length() < b.length())
      {
            a.swap(b);
            resultIsNegative = true;//结果为负
      }
      else if(a.length() == b.length())
      {
            t=0;
            while(true)
            {
                if(a != b)//找到第一个不相等的数
                  break;
                else
                  ++t;
            }
            if(a < b)//计算结果为负的
            {
                resultIsNegative = true;
                a.swap(b);
            }
      }

      Minus(a, b, result);//减
      
      while(*result.begin() == '0')//去除前面的0
      {
            result.erase(result.begin());
      }
      if(resultIsNegative)//结果是负的
      {
            result.insert(result.begin(), '-');
      }
      //补回'.'号前面的0,因为-0.2155+0.544 或 0.2155-0.544这种情况会把.号前面的0删除除
      if(aIndex!=string::npos || bIndex!=string::npos)
      {
            t = result.find_first_of('.');
            if(t == 0)//结果是正的
                result.insert(result.begin(), '0');
            else if(resultIsNegative&& t==1)//结果是负的而且'.'号位置为1(如:结果为-.95)
                result.insert(++result.begin(), '0');
      }
    }

    if(result.find_first_of('.') != string::npos)//处理小数点后面多余的0
    {
      while(*--result.end() == '0')
      {
            result.erase(--result.end());
      }
      if(*--result.end() == '.')//去除小数点
      {
            result.erase(--result.end());
      }
    }
}
//计算a+b
string a_Plus_b(stringa, string   b)
{   
    string result;
    bool aIsNegative = false; //a是否是负数
    bool bIsNegative = false; //b是否是负数
   
    if(a == '-')
      aIsNegative = true;
    if(b == '-')
      bIsNegative = true;
    if(a == '+')
      a.erase(0, 1);//正数有加号,直接去除
    if(b == '+')
      b.erase(0, 1);
   
    if( (aIsNegative==false) && (bIsNegative==false) )//a,b同时为正
    {
      if(a.compare("0")==0 && b.compare("0")==0)//把0+0这种情况处理掉
      {
            result.insert(result.begin(), '0');
            return result;
      }
      AddZero(0, a, b, result);//交给AddZero处理
    }
    else if((aIsNegative==true) && (bIsNegative==true))//a,b同时为负
    {
      a.erase(0, 1);//删除a的减号
      b.erase(0, 1);//删除b的减号
      AddZero(0, a, b, result);//交给AddZero处理
      result.insert(result.begin(), '-');//最后添加负号
    }
    else//a,b一正一负
    {
      if(aIsNegative == true)//a是负数
      {
            a.swap(b);
      }
      
      if(0 == b.compare(1, b.length(), a))//判断a,b是否相等
      {
            result.append(1, '0');
      }
      else
      {
            b.erase(b.begin());//删除负号
            AddZero(1, a, b, result);//交给AddZero处理
      }
    }
    return result;
}
//计算a-b
string a_Minus_b(string a, string b)
{
    if(b == '-')
      b.erase(b.begin());
    else if(b == '+')
      b = '-';
    else
      b.insert(b.begin(), '-');

    return a_Plus_b(a, b);
}
int main()
{
    stringa, b, result1;
    cout<<"请输入两个数:"<<endl;
    cin>>a>>b;
    /*****
   检查a,b是否正确
    *****/
    result1 = a_Plus_b(a, b);
    cout<<a<<"+"<<b<<"="<<result1<<endl;
   
    result1 = a_Minus_b(a, b);
    cout<<a<<"-"<<b<<"="<<result1<<endl;
   
    return 0;
}

0xAA55 发表于 2014-3-2 17:19:25

我已经把你的代码修改成更容易阅读的代码。

葡萄成熟时 发表于 2014-3-2 19:32:48

0xAA55 发表于 2014-3-2 17:19
我已经把你的代码修改成更容易阅读的代码。

:victory:好的

葡萄成熟时 发表于 2014-3-3 23:15:57

葡萄成熟时 发表于 2014-3-2 16:25
#include
#include
using namespace std;


代码风格已上传到论坛,你去下来看看,我的是从那里学来的:lol
页: [1]
查看完整版本: 大数加减我的做法