大数加减我的做法
大数加减算法给大家分享,这程序可以算很大的数还有很长的精度,我测了没发现有问题,如果大家发现问题麻烦告诉一声。首先把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
#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
我已经把你的代码修改成更容易阅读的代码。
:victory:好的 葡萄成熟时 发表于 2014-3-2 16:25
#include
#include
using namespace std;
代码风格已上传到论坛,你去下来看看,我的是从那里学来的:lol
页:
[1]