针对精确表达浮点数 -- 编程之美那节处理大整数溢出的情况,写了这个代码:
对于加法,直接相加并在进行时考虑进位,也可以先相加,最后考虑进位问题。
减法,有加法类似,但此处未处理异号等情况,只考虑第一参数大于后面的,(考虑后面情况,需先判断大小关系,是否异号,是的话借用加法操作即可)。
乘法的话此处直接乘的未考虑优化其他的方法,加法雷同,先相加,最后考虑进位问题。
除法有点麻烦,的试商,调整余数,并且用减法来获得每位的商值!实现起来容易出问题。
代码如下:
#include <iostream>
#include <string>
#include <algorithm>
#include <cassert>
using namespace std;
const int MAX_NUM = 1000;
template <class T>
struct Huge_data
{
T data[MAX_NUM];
int len;
};
typedef Huge_data<int> HD;
void print_bigdata(HD &data);
void add(const HD &a,const HD &b,HD &res);
int cmp(const HD &a,const HD &b);
void subtract(const HD &a,const HD &b,HD &res);//保证a>=b,或者当a<b时,用b-a再更改负号
void str_to_hd(HD &a,string str);
void multi(const HD &a,const HD &b,HD &res);
void div(const HD a,const HD b,HD &res,HD &left);
int main()
{
// HD first ={{1,2,3,4,5,6},6};
// HD second={{9,9,9,9,5,4,3,2,1},9};
// print_bigdata(first);
// print_bigdata(second);
/*
add(first,second,second);
print_bigdata(second);
subtract(second,first,second);
print_bigdata(second);
*/
HD first,second;
HD res;
string str_my;
cin>>str_my;
str_to_hd(first,str_my);
cin>>str_my;
str_to_hd(second,str_my);
//add(first,second,second);
//print_bigdata(second);
//subtract(second,first,second);
//print_bigdata(second);
multi(first,second,res);
print_bigdata(res);
div(first,second,res,first);
print_bigdata(res);//商
print_bigdata(first);//余数
return 0;//正常退出!
}
void add(const HD &a,const HD &b,HD &res)
{
int min_len = min(a.len,b.len);
assert(min_len <= MAX_NUM);
int carry = 0;
for (int i = 0;i < min_len;i++)
{
int temp = a.data[i] + b.data[i] + carry;
carry = 0;
if (temp >= 10)//尽量不要取某
{
res.data[i] = temp - 10 ;
carry = 1;
}
else
{
res.data[i] = temp;
}
}
int max_len = max(a.len,b.len);
assert(max_len <= MAX_NUM);
const HD *c;
if (a.len > b.len)
{
c = &a;
}
else
{
c = &b;
}
for (int j = min_len; j < max_len;j++)
{
int temp = c->data[j] + carry;
carry = 0;
if (temp >= 10)//尽量不要取某
{
res.data[j] = temp - 10 ;
carry = 1;
}
else
{
res.data[j] = temp;
}
}
res.len = max_len;
//最后是否有进位
if(carry == 1)
{
assert(max_len+1 <= MAX_NUM);
res.data[max_len] = 1;
res.len = max_len+1;
}
}
void print_bigdata(HD &hdata)
{
for (int i = hdata.len-1;i >=0;i--)
{
cout<<hdata.data[i];
}
cout<<endl;
}
void str_to_hd(HD &a,string str)
{
a.len = str.size();
for(int i = str.size()-1;i >= 0;i--)
{
a.data[i] = str[str.size()-1-i]-'0';
}
if (a.len == 0)//默认为0
{
a.len = 1;
a.data[0] = 0;
}
}
int cmp(const HD &a,const HD &b)
{
if (a.len > b.len) return 1;
else if (a.len < b.len) return -1;
else
{
for(int i = a.len-1;i >=0;i--)
{
return a.data[i]-b.data[i];
}
}
return -1;
}
void subtract(const HD &a,const HD &b,HD &res)//保证a>=b,或者当a<b时,用b-a再更改负号
{
assert(cmp(a,b)>=0);
int min_len = min(a.len,b.len);
assert(min_len <= MAX_NUM);
int carry = 0;
for (int i = 0;i < min_len;i++)
{
int temp = a.data[i] - b.data[i] - carry;
carry = 0;
if (temp < 0)//尽量不要取某
{
res.data[i] = temp + 10 ;
carry = 1;
}
else
{
res.data[i] = temp;
}
}
int max_len = max(a.len,b.len);
assert(max_len <= MAX_NUM);
const HD *c;
if (a.len > b.len)
{
c = &a;
}
else
{
c = &b;
}
for (int j = min_len; j < max_len;j++)
{
int temp = c->data[j] - carry;
carry = 0;
if (temp < 0)//尽量不要取某
{
res.data[j] = temp + 10 ;
carry = 1;
}
else
{
res.data[j] = temp;
}
}
res.len = max_len;
//最后是否有借位,不可能发生!!因a>=b
//(carry == 1)
//但的处理长度,可能a == b全0
while(res.len>1&&res.data[res.len-1] == 0)res.len--;//处理头为长度,且保证长度大于等于1
}
void multi(const HD &a,const HD &b,HD &res)
{
memset(&res,0,sizeof(HD));
for(int i = 0; i < a.len;i++)
{
for(int j = 0; j < b.len;j++)
{
res.data[i+j] += a.data[i]*b.data[j];
}
}
int carry = 0;
for(int k = 0; k < a.len+b.len;k++)
{
int temp = (res.data[k]+carry);
carry = temp / 10;
res.data[k] = temp % 10;
}
int count = a.len+b.len;
while(carry > 0)//有进位
{
res.data[count++] = carry % 10;
carry = carry / 10;
}
res.len = count --;
//去除一些最高位为0的情况
while(res.len>1&&res.data[res.len-1] == 0)res.len--;//处理头为长度,且保证长度大于等于1
}
void div(const HD a,const HD b,HD &res,HD &left)//left 必须是干净的值否则会影响
{
memset(&left,0,sizeof(HD));
memset(&res,0,sizeof(HD));
left.len = 0;
left.data[0] = 0;//理解开头的处理(由于余数小,则i++,使得余数left变大,直达大于除数,开始处理)
for(int i = a.len-1; i >= 0;i--)
{
// 以下处理余数
for(int j = left.len -1;j >= 0;j--)//处理余数向右移动
{
left.data[j+1] = left.data[j] ;
}
left.len++;//长度加1
//给予被除数的一位
left.data[0] = a.data[i];//放在末尾位置
//res.data[i] = 0;//清0
//当余数大于除数就处理,-- 通过减法实现的除法
int val;
while((val = cmp(left,b)) >= 0)
{
subtract(left,b,left);
//就是此处处理有点问题!改正 或者在处理余数时处理!!!
if(left.len == 1&&left.data[0]== 0)//减法会出来一个0,使有长度!
{
left.len = 0;
left.data[0] = 0;
}
res.data[i]++;//商加加 (可以第一次处理时记住长度,或下面处理)
if(val == 0)
{
break;
}
}
}
if(left.len == 0)
{
left.len = 1;
left.data[0] = 0;
}
res.len = a.len;
while(res.len > 1 && res.data[res.len-1] == 0 )res.len--;//处理头为长度,且保证长度大于等于1
}