大整数(正负都可)的三则运算,不包括除法,以下代码含有运算符重载。个人记录方便自己回顾
#include <iostream>
#include <string>
#include <algorithm>
#include <exception>
using namespace std;
class BigInteger{
private:
string digit;//数字字符串
enum P_NTag{
POSITIVE = 1,
NEGTIVE = -1
} isNeg;//正负标志位,1为正,-1为负
/*判断是否为数字*/
bool isNum(const string str){
for(int i = 0; i < str.length(); i++){
if(str[i] < '0' || str[i] > '9'){
switch (i)
{
case 0://第一位如果为正负符号则正常,可以退出switch
if(str[i] == '+' || str[i] == '-') break;
default:
return false;
break;
}
}
}
return true;
}
/*格式化数字,将多余的0去掉*/
void formatTrim(string &digit){
int k = 0;
//这里应该避免检查最后一位,最后一位前的0可以全部去除
for(k = 0; k < digit.length() - 1 && digit[k] == '0'; k++);
digit.erase(0, k);
}
/*加法运算*/
int add_c(char a, char b, int carry, char &x){//辅助函数,计算数字字符加法,返回进位值
int res = (a - '0') + (b - '0') + carry;
x = (res % 10) + '0';
if(res >= 10) return 1;
else return 0;
}
string Plus(BigInteger a, BigInteger b){
int carry = 0;//进位
int len_a = a.digit.length();
int len_b = b.digit.length();
string res = "";
//判断两数是否同号,并给出相应的操作
char x;//保存当前位计算结果
int i = len_a - 1, j = len_b - 1;//两个大数字符串指针
switch ((int)a.isNeg * (int)b.isNeg)
{
case -1://异号改为减法
return Minus(a, -b);
default://case 1
while(i >= 0 && j >= 0){
carry = add_c(a.digit[i--], b.digit[j--], carry, x);
res = x + res;
}
//下面的计算确保所有数的所有位数均进行了计算
while (j >= 0){
carry = add_c(b.digit[j--], '0', carry, x);
res = x + res;
}
while (i >= 0){
carry = add_c(a.digit[i--], '0', carry, x);
res = x + res;
}
if(carry){ //两个数的位数都计算完了还有进位,则另补一个1
res = '1' + res;
carry = 0;
}
//根据符号返回结果
if(a.isNeg == POSITIVE) return res;
else return '-' + res;
}
}
/*减法运算*/
int minus_c(char a, char b, int borrow, char &x){
int res = (a - '0') - (b - '0') + borrow;
x = (res + 10) % 10 + '0';
if(res < 0) return -1;
else return 0;
}
string Minus(const BigInteger a, BigInteger b){
int borrow = 0;//借位
int len_a = a.digit.length(), len_b = b.digit.length();
string res = "";
//根据正负号提供对应的操作
char x;//保存当前位计算结果
int i = len_a - 1, j = len_b - 1;//两个大数字符串指针
switch ((int)a.isNeg * (int)b.isNeg)
{
case -1://异号改为加法
return Plus(a, -b);
default://case 1
while(i >= 0 && j >= 0){
borrow = minus_c(a.digit[i--], b.digit[j--], borrow, x);
res = x + res;
}
//由于将所有的case 1的情况放在一起,所以必须将所有数的所有位都完成减法运算
while(j >= 0){//减数未完成,用0减
borrow = minus_c('0', b.digit[j--], borrow, x);
res = x + res;
}
while(i >= 0){//被减数未完成,减去0
borrow = minus_c(a.digit[i--], '0', borrow, x);
res = x + res;
}
//上述运算完成后,还要根据borrow判断是否进行数值转换
switch (borrow)
{
case -1://borrow=-1说明计算还未完成,需要进行数值转换,类似于取补码
for(int k = res.length() - 1, _borrow = 0; k >= 0; k--){
_borrow = minus_c('0', res[k], _borrow, res[k]);
}
//上述操作完成后,结果的正负值是 被减数乘以borrow(值为-1)后的正负 决定的
if(a.isNeg == POSITIVE) res = '-' + res;
return res;
default://borrow=0则计算完成,根据被减数的正负情况调整一下即可
if(a.isNeg == NEGTIVE) res = '-' + res;
return res;
}
}
}
/*乘法运算*/
string multi(string a, string b){
int longer = max(a.length(), b.length());//取长的那一个
//递归终止条件
if(a.length() == 1 && b.length() == 1){
int _a = a[0] - '0';
int _b = b[0] - '0';
return to_string(_a * _b);
}
//使量字符串长度相同,短的补0(对齐补零)
// while(a.length() < longer) a = "0" + a;
// while(b.length() < longer) b = "0" + b;
a = string(longer - a.length(), '0') + a;//较上面的高效一丢丢
b = string(longer - b.length(), '0') + b;
//a*b=c2*10^n+c1*10^(n/2)+c0, c1=(a1+a0)*(b1+b0)-(c2+c0), c2=(a1*b1), c0=a0*b0
string a1, a0, a1_a0;
string b1, b0, b1_b0;
string c2, c1, c0, c2_c0;
int half = longer >> 1;
a1 = a.substr(0, half);
a0 = a.substr(half);
b1 = b.substr(0, half);
b0 = b.substr(half);
c2 = multi(a1, b1);
c0 = multi(a0, b0);
a1_a0 = Plus(a1, a0);
b1_b0 = Plus(b1, b0);
c2_c0 = Plus(c2, c0);
c1 = Minus(multi(a1_a0, b1_b0), c2_c0);
//左移相应位数
int n = (longer + 1) >> 1; //对应10的幂
c2 = c2 + string(2 * n, '0');
c1 = c1 + string(n, '0');
return Plus(Plus(c2, c1), c0);
}
string Multi(BigInteger a, BigInteger b){
switch ((int)a.isNeg * (int)b.isNeg)
{
case 1:
return multi(a.digit, b.digit);
break;
default:
return "-" + multi(a.digit, b.digit);
break;
}
}
/**
* * * * * *公私属性、函数分界线* * * * * *
* */
public:
BigInteger(string digit = "0"):isNeg(POSITIVE){//构造函数,其中正负标志位默认位1
if(digit.empty() || !isNum(digit)){
cout << digit + ">>>";
throw "Invaild Parameters!";
}
else{
/*正负判断 判断第一位有无正负符号,并改变对应的正负标志位*/
isNeg = digit[0] == '-' ? NEGTIVE : POSITIVE;
if(digit[0] == '+' || digit[0] == '-') digit.erase(0, 1);//将正负符号去掉
/*格式化数字,去除多余的0*/
formatTrim(digit);
/*如果数字为-0,则将正负标志设为正*/
if(digit == "0") isNeg = POSITIVE;
this->digit = digit;
}
}
/**
* 运算符重载
* */
BigInteger operator +(){//一元运算符
return *this;
}
BigInteger operator +(const BigInteger b){//二元运算符
return BigInteger(Plus(*this, b));
}
BigInteger operator -(){//一元运算符
this->isNeg = (enum P_NTag)(NEGTIVE * this->isNeg);
return *this;
}
BigInteger operator -(const BigInteger b){
return BigInteger(Minus(*this, b));
}
BigInteger operator *(const BigInteger b){
return BigInteger(Multi(*this, b));
}
//赋值运算符
void operator =(const BigInteger &b){
digit = b.digit;
isNeg = b.isNeg;
}
void operator = (const string &str){
BigInteger bi = BigInteger(str);
digit = bi.digit;
isNeg = bi.isNeg;
}
//关系运算符
bool operator ==(const BigInteger b){
return (digit == b.digit && isNeg == b.isNeg);
}
bool operator !=(const BigInteger b){
return !(*this == b);
}
//输入输出运算符
friend istream& operator >>(istream &in, BigInteger &a){//这里必须是友元函数
string str;
in >> str;
a = str;
return in;
}
friend ostream& operator <<(ostream &out, const BigInteger &a){
return out << (a.isNeg == POSITIVE ? a.digit : "-" + a.digit);//根据正负值输出正确的数字
}
};//BigInteger
int main(){
try{
while (1){
BigInteger a;
BigInteger b;
cin >> a >> b;
cout << "a = " << a << " b = " << b << endl;
if (a == b)
cout << "a == b" << endl;
else
cout << "a != b" << endl;
cout << "a + b = " << a + b << endl;
cout << "a - b = " << a - b << endl;
cout << "a * b = " << a * b << endl;
}
} catch(const char* &str){
cout << str;
}
return 0;
}