找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 3046|回复: 5

大数加减我的做法

[复制链接]
发表于 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 | 显示全部楼层

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. //加法
  5. void Plus(string a, string b, string &result)
  6. {
  7.     string::size_type i, j, k;
  8.     int temp=0;//存放进位
  9.     //同为相加取余,temp保存进位
  10.     for(i=a.length()-1, j=b.length()-1, k=result.length()-1;  i!=0 && j!=0 && k!=0;  --i,--j,--k)
  11.     {
  12.         if(a == '.')//'.'号不计算
  13.         {
  14.             result[k] = '.';
  15.             continue;
  16.         }
  17.         else//不是'.'号就计算
  18.         {
  19.             temp += a - '0' + b[j] - '0';
  20.             result[k] = temp % 10 + 48;
  21.             temp /= 10;
  22.         }
  23.     }

  24.     for(; i!=0; --i,--k)//a可能还有数字
  25.     {
  26.         temp += a - '0';
  27.         result[k] = temp % 10 + 48;
  28.         temp /= 10;
  29.     }
  30.     if(temp > 0)//最后一个进位
  31.         result[k] = temp + 48;
  32. }
  33. //减法
  34. void Minus(string a, string b, string &result)
  35. {
  36.     string::size_type i, j, k, t;

  37.     for(i=a.length()-1, j=b.length()-1, k=result.length()-1;  i!=0 && j!=0 && k!=0;  --i,--j,--k)
  38.     {
  39.         if(a >= b[j])
  40.         {
  41.             if(a == '.')//'.'号不计算
  42.             {
  43.                 result[k] = '.';
  44.                 continue;
  45.             }
  46.             result[k] = a - b[j] + 48;
  47.         }
  48.         else//向前借1
  49.         {
  50.             result[k] = a - b[j] + 10 + 48;
  51.             t = i - 1;
  52.             while(a[t]=='0' || a[t] =='.')//找到第一个不是0的数
  53.             {
  54.                 if(a[t] == '0')
  55.                     a[t] = '9';//0直接变成9
  56.                 --t;
  57.             }
  58.             a[t] -= 1;//找到了第一个不是0的数,减一
  59.         }
  60.     }
  61.     while(i !=0 )//a可能还有数
  62.     {
  63.         result[k] = a;
  64.         --i;
  65.         --k;
  66.     }
  67. }
  68. //处理有或没有小数点的情况,function用来标识是做加法还是做减法
  69. void AddZero(int function, string a, string b, string &result)
  70. {
  71.     string::size_type aIndex, bIndex, t; //a和b的小数点号位置
  72.     unsined dif, aRight, bRight;//a,b小数位数差,a的小数位数,b的小数位数
  73.     bool resultIsNegative = false;//判断结果是否是负的
  74.    
  75.     result.append(a.length() + b.length(), '0');//给result负初值
  76.     a.insert(a.begin(), '0');//在a前面添加0
  77.     b.insert(b.begin(), '0');
  78.     aIndex = a.find_first_of('.');//获取a的小数点号位置
  79.     bIndex = b.find_first_of('.');//获取b的小数点号位置

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

  82.         aRight = a.length() - aIndex - 1;//a的小数位数
  83.         bRight = b.length() - bIndex - 1;//b的小数位数
  84.         if(aRight > bRight)
  85.         {
  86.             dif = aRight - bRight;//a,b小数位数差
  87.             b.append(dif, '0');//在b末尾添加dif个0,跟a的小数位数相等,方便计算
  88.         }
  89.         else if(aRight < bRight)
  90.         {
  91.             dif = bRight - aRight;//a,b小数位数差
  92.             a.append(dif, '0');//在a末尾添加dif个0,跟b的小数位数相等,方便计算
  93.         }
  94.     }
  95.     else if(aIndex!=string::npos && bIndex==string::npos)//a有小数点,b没有
  96.     {
  97.         aRight = a.length() - aIndex - 1;//a的小数位数
  98.         b.append(1, '.');//在b末尾添加.号
  99.         b.append(aRight, '0');//在b末尾添加aRight个0
  100.     }
  101.     else if(aIndex==string::npos && bIndex!=string::npos)//b有小数点,a没有
  102.     {
  103.         bRight = b.length() - bIndex - 1;//b的小数点位数
  104.         a.append(1, '.');//在b末尾添加.号
  105.         a.append(bRight, '0');//在a末尾添加bRight个0
  106.     }

  107.     if(function == 0)
  108.     {
  109.         if(a.length() < b.length())
  110.         {
  111.             a.swap(b);//保证a.length()>=b.length()
  112.         }
  113.         Plus(a, b, result);//加
  114.         while(*result.begin() == '0')
  115.         {
  116.             result.erase(result.begin());//清除前面的0
  117.         }
  118.         //补回.号前面的0,因为0.2155+0.544这种情况会把'.'号前面的0删除除
  119.         if(aIndex!=string::npos || bIndex!=string::npos)
  120.         {
  121.             t = result.find_first_of('.');
  122.             if(t == 0)
  123.                 result.insert(result.begin(), '0');
  124.         }
  125.     }
  126.     else
  127.     {
  128.         if(a.length() < b.length())
  129.         {
  130.             a.swap(b);
  131.             resultIsNegative = true;//结果为负
  132.         }
  133.         else if(a.length() == b.length())
  134.         {
  135.             t=0;
  136.             while(true)
  137.             {
  138.                 if(a[t] != b[t])//找到第一个不相等的数
  139.                     break;
  140.                 else
  141.                     ++t;
  142.             }
  143.             if(a[t] < b[t])//计算结果为负的
  144.             {
  145.                 resultIsNegative = true;
  146.                 a.swap(b);
  147.             }
  148.         }

  149.         Minus(a, b, result);//减
  150.         
  151.         while(*result.begin() == '0')//去除前面的0
  152.         {
  153.             result.erase(result.begin());
  154.         }
  155.         if(resultIsNegative)//结果是负的
  156.         {
  157.             result.insert(result.begin(), '-');
  158.         }
  159.         //补回'.'号前面的0,因为-0.2155+0.544 或 0.2155-0.544这种情况会把.号前面的0删除除
  160.         if(aIndex!=string::npos || bIndex!=string::npos)
  161.         {
  162.             t = result.find_first_of('.');
  163.             if(t == 0)//结果是正的
  164.                 result.insert(result.begin(), '0');
  165.             else if(resultIsNegative  && t==1)//结果是负的而且'.'号位置为1(如:结果为-.95)
  166.                 result.insert(++result.begin(), '0');
  167.         }
  168.     }

  169.     if(result.find_first_of('.') != string::npos)//处理小数点后面多余的0
  170.     {
  171.         while(*--result.end() == '0')
  172.         {
  173.             result.erase(--result.end());
  174.         }
  175.         if(*--result.end() == '.')//去除小数点
  176.         {
  177.             result.erase(--result.end());
  178.         }
  179.     }
  180. }
  181. //计算a+b
  182. string a_Plus_b(string  a, string   b)
  183. {   
  184.     string result;
  185.     bool aIsNegative = false; //a是否是负数
  186.     bool bIsNegative = false; //b是否是负数
  187.    
  188.     if(a[0] == '-')
  189.         aIsNegative = true;
  190.     if(b[0] == '-')
  191.         bIsNegative = true;
  192.     if(a[0] == '+')
  193.         a.erase(0, 1);//正数有加号,直接去除
  194.     if(b[0] == '+')
  195.         b.erase(0, 1);
  196.    
  197.     if( (aIsNegative==false) && (bIsNegative==false) )//a,b同时为正
  198.     {
  199.         if(a.compare("0")==0 && b.compare("0")==0)//把0+0这种情况处理掉
  200.         {
  201.             result.insert(result.begin(), '0');
  202.             return result;
  203.         }
  204.         AddZero(0, a, b, result);//交给AddZero处理
  205.     }
  206.     else if((aIsNegative==true) && (bIsNegative==true))//a,b同时为负
  207.     {
  208.         a.erase(0, 1);//删除a的减号
  209.         b.erase(0, 1);//删除b的减号
  210.         AddZero(0, a, b, result);//交给AddZero处理
  211.         result.insert(result.begin(), '-');//最后添加负号
  212.     }
  213.     else//a,b一正一负
  214.     {
  215.         if(aIsNegative == true)//a是负数
  216.         {
  217.             a.swap(b);
  218.         }
  219.         
  220.         if(0 == b.compare(1, b.length(), a))//判断a,b是否相等
  221.         {
  222.             result.append(1, '0');
  223.         }
  224.         else
  225.         {
  226.             b.erase(b.begin());//删除负号
  227.             AddZero(1, a, b, result);//交给AddZero处理
  228.         }
  229.     }
  230.     return result;
  231. }
  232. //计算a-b
  233. string a_Minus_b(string a, string b)
  234. {
  235.     if(b[0] == '-')
  236.         b.erase(b.begin());
  237.     else if(b[0] == '+')
  238.         b[0] = '-';
  239.     else
  240.         b.insert(b.begin(), '-');

  241.     return a_Plus_b(a, b);
  242. }
  243. int main()
  244. {
  245.     string  a, b, result1;
  246.     cout<<"请输入两个数:"<<endl;
  247.     cin>>a>>b;
  248.     /*****
  249.      检查a,b是否正确
  250.     *****/
  251.     result1 = a_Plus_b(a, b);
  252.     cout<<a<<"  +  "<<b<<"  =  "<<result1<<endl;
  253.    
  254.     result1 = a_Minus_b(a, b);
  255.     cout<<a<<"  -  "<<b<<"  =  "<<result1<<endl;
  256.    
  257.     return 0;
  258. }
复制代码

点评

编码风格我很喜欢  发表于 2014-3-2 20:22
回复 赞! 1 靠! 0

使用道具 举报

发表于 2014-3-2 17:19:25 | 显示全部楼层
我已经把你的代码修改成更容易阅读的代码。
回复 赞! 靠!

使用道具 举报

 楼主| 发表于 2014-3-2 19:32:48 | 显示全部楼层
0xAA55 发表于 2014-3-2 17:19
我已经把你的代码修改成更容易阅读的代码。

好的
回复 赞! 靠!

使用道具 举报

 楼主| 发表于 2014-3-3 23:15:57 | 显示全部楼层
葡萄成熟时 发表于 2014-3-2 16:25
[code]#include
#include
using namespace std;

代码风格已上传到论坛,你去下来看看,我的是从那里学来的
回复 赞! 靠!

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-11-22 02:37 , Processed in 0.039039 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表