您的位置:首页 > 其它

大整数运算(支持正负数、加减乘除)

2017-02-22 05:22 435 查看
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
using namespace std;

const int maxn = 3000;       //大整数位数

struct BigNumber
{
int len, s[maxn];       // 从0开始存个位
bool positive;          //正号 T非负数(包括0) F负数

//构造函数
BigNumber()
{
memset(s, 0, sizeof(s));
len = 1;
positive = true;
}

BigNumber(int num)
{
memset(s, 0, sizeof(s));
*this = num;
}

BigNumber(const char* num)
{
*this = num;
}

//取反
BigNumber(const BigNumber &b,bool negate = true)
{
memset(s, 0, sizeof(s));
len = b.len;
positive = b.positive;
if (!negate)
positive = !b.positive;
for (int i = 0; i < len; i++)
{
s[i] = b.s[i];
}
}

//取指定位置
BigNumber(const BigNumber &b, int start, int end)
{
memset(s, 0, sizeof(s));
len = end - start +1;
positive = b.positive;
for (int i = 0; i < len; i++,start++)
{
s[i] = b.s[start];
}
}

//字符串直等
BigNumber operator = (const char* num)
{
memset(s, 0, sizeof(s));
len = strlen(num);
if (num[0] == '-')    //符号位不计入数组
positive = false;
else
positive = true;

for (int i = 0; i < len; i++)
s[i] = num[len - i - 1] - '0';

if (!positive)
{
len -= 1;
s[len] = 0;
}
return *this;
}

//int直等
BigNumber operator = (int num)
{
char str[maxn];
sprintf(str, "%d", num);
*this = str;   //直接用字符串直等
return *this;
}

//返回字符串形式 const表面x.str()不会改变x
string str() const
{
string res = "";
for (int i = 0; i < len; i++)
{
res = (char)(s[i] + '0') + res;
}
if (res == "")
res = "0";
else if (!positive)
res = '-' + res;
return res;
}

void SetZero()
{
memset(s, 0, sizeof(s));
positive = true;
len = 1;
}

void Negate()
{
positive = !positive;
}

//数组取反
void Reverse()
{
for (int i = 0; i < len / 2; i++)
{
int t = s[i];
s[i] = s[len - 1 - i];
s[len - 1 - i] = t;
}
}

bool Zero() const
{
if (len <= 1 && s[0] == 0)
return true;
return false;
}

void Print()
{
if (positive)
cout << "正数: " << str() << endl;
else
cout << "负数: " << str() << endl;
}

//重载 + 号
BigNumber operator + (const BigNumber &b) const
{
if (positive && !b.positive)
{
BigNumber c(b, false);
return *this - c;
}
else if (!positive && b.positive)
{
BigNumber c(*this,false);
return b- c;
}
else
{
BigNumber c;
c.len = 0;
if (positive && b.positive)
{
c.positive = true;
}
else if (!positive && !b.positive)
{
c.positive = false;
}
for (int i = 0, g = 0; i < max(len, b.len) + 1; i++)
{
int x = s[i] + b.s[i] + g;
c.s[c.len++] = x % 10;
g = x / 10;
}

//检查前导0
int j = 0;
for (j = c.len - 1; j >= 0; j--)
if (c.s[j])
break;
c.len = j + 1;
return c;
}
}

//重载 - 号
//作减法的时候我们稍微修改一下步骤,先判断没有符号的情况下哪个大,然后用大数-小数,最后加正负
BigNumber operator - (const BigNumber &b) const
{
if (!positive  && !b.positive)   //均为负数
{
BigNumber a1(*this, false);
BigNumber c(b, false);
return c - a1;
}
else if (!positive && b.positive)  //a负b正
{
BigNumber a1(*this,false);
BigNumber c;
c = a1 + b;
c.positive = false;
return c;
}
else if (positive && !b.positive) //a正b负
{
BigNumber c(b, false);
return *this + c;
}
else        //均为正数
{
BigNumber c;
c.len = 0;
if (*this < b)
{
c = b - *this;
c.positive = false;
return c;
}

for (int i = 0, g = 0; i < max(len, b.len); i++)
{
int x = s[i] - b.s[i] - g;
if (x < 0)
g = 1;
else
g = 0;
c.s[c.len++] = x + g * 10;
}

//检查前导0
int j = 0;
for (j = c.len - 1; j >= 0; j--)
if (c.s[j])
break;
c.len = j + 1;
return c;
}
}

//重载 * 号
BigNumber operator * (const BigNumber &b) const
{
if (Zero() || b.Zero())
{
BigNumber c(0);
return c;
}
BigNumber c;
c.len = 0;

int Multiplied = 2;   //被乘数
int times = len;       //相乘次数 按最小的来
if (b.len < times)
{
Multiplied = 1;
times = b.len;
}

for (int i = 0; i < times; i++)
{
if (Multiplied == 1)  // this 为被乘数  注意要加上上一步乘法剩余的
{
for (int j = 0, g=0; j < len + 1; j++)
{
int x = b.s[i] * s[j] + g;
g = x / 10 + (c.s[i + j] + x%10) / 10;
c.s[i+j] = (x % 10 + c.s[i+j]) % 10;
}
}
else
{
for (int j = 0, g = 0; j < b.len + 1; j++)
{
int x = s[i] * b.s[j] + g;
g = x / 10 + (c.s[i + j] + x % 10) / 10;
c.s[i + j] = (x % 10 + c.s[i + j]) % 10;
}
}
}
//检查前导0
int j = 0;
for (j = len+b.len; j >= 0; j--)
if (c.s[j])
break;
c.len = j + 1;

if ((positive && !b.positive) || (!positive && b.positive))
c.positive = false;

return c;
}

//重载 / 号 只支持整数 若 a<b a/b = 0
BigNumber operator / (const BigNumber &b) const
{
BigNumber c(*this,false);
if (Zero() || len < b.len || (*this < b && positive) || (c<b && c.positive) )
c.SetZero();
else if (b.Zero())
{
c.SetZero();
cout << "被除数为0" << endl;
}
else if (*this == b)
c = 1;
else if (c == b)
c = -1;
else
{
bool flag = true;                       //先把符号记下来 后面做乘除的时候都不要带符号
if ((positive && !b.positive) || (!positive && b.positive))
flag = false;

BigNumber a1(*this);               //这里用两个变量来做运算 其实就是绝对值 防止后面做 >= 判断的时候出错
a1.positive = true;
BigNumber a2(b);
a2.positive = true;

c.SetZero();
c.len = 0;
int len1 = a1.len - 1;
int len2 = a2.len - 1;
int pos = a1.len - a2.len;     //除法初始位置 如1234/99 pos = 1 那么(pos-0+1)就是商的位数
while (a1.s[len1] == a2.s[len2] && len2 >= 0)
{
len1--;
len2--;
}
if (len2 >= 0)
{
if (a1.s[len1] < a2.s[len2])
pos -= 1;
}

BigNumber d(a1, pos, len - 1);
while (true)
{
c.s[c.len] = 1;       // 当前位的商
while (d >= a2*c.s[c.len])
{
c.s[c.len]++;
}
c.s[c.len] --;
c.len++;
if (pos == 0)
break;
d = (BigNumber)((d - a2*c.s[c.len - 1]) * 10) + (BigNumber)a1.s[--pos];   //余数+下一位
}
c.Reverse();   //数组翻转
c.positive = flag;
}
return c;
}

//重载 +=
BigNumber operator += (const BigNumber &b)
{
*this = *this + b;
return *this;
}

bool operator < (const BigNumber &b) const
{
if (positive && !b.positive)
return false;
else if (!positive && b.positive)
return true;
if (positive && b.positive)
{
if (len != b.len)
return len < b.len;
for (int i = len - 1; i >= 0; i--)
if (s[i] != b.s[i])
return s[i] < b.s[i];
}
else
{
if (len != b.len)
return len > b.len;
for (int i = len - 1; i >= 0; i--)
if (s[i] != b.s[i])
return s[i] > b.s[i];
}
return false;
}

bool operator > (const BigNumber &b) const
{
return b < *this;
}

bool operator <= (const BigNumber &b) const
{
return !(b < *this);
}

bool operator >= (const BigNumber &b) const
{
return !(*this < b);
}

bool operator != (const BigNumber &b) const
{
return b < *this || *this < b;
}

bool operator == (const BigNumber &b) const
{
return !(*this != b);
}
};

//重载cin和cout  其实也可以直接定义string
istream &operator >> (istream &in, BigNumber &x)
{
string s;
in >> s;
x = s.c_str();
return in;
}

ostream &operator << (ostream &out, const BigNumber &x)
{
out << x.str();
return out;
}

int main()
{
BigNumber b1, b2;
while (cin >> b1>>b2)
{
//BigNumber b1(s1.c_str());
//BigNumber b2(s2.c_str());
//b1.Print();
//b2.Print();
cout << (b1+b2).str() << endl;
cout << (b1 - b2).str() << endl;
cout << (b1*b2).str() << endl;
cout << (b1 / b2).str() << endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: