大整数运算(支持正负数、加减乘除)
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; } }
相关文章推荐
- 用位运算实现两个整数的加减乘除运算
- 整数运算(加减乘除的底层操作)
- 只用位运算实现整数的加减乘除运算
- 大整数运算之加减乘除
- VC++大数乘法计算,支持1000位大整数乘法运算
- 利用位运算判断整数的正负
- 关于大整数的加减乘除求余运算 java
- 位运算实现加减乘除、求补、比较、正负判断
- 位运算---只使用位运算实现整数的加减乘除
- 超大整数的加减乘除运算及X进制转换
- 用位运算实现两个整数的加减乘除运算
- 用位运算实现两个整数的加减乘除运算
- 位运算实现加减乘除、求补、比较、正负判断
- 位运算实现加减乘除、求补、比较、正负判断
- if结构实现迷你计算器,支持加减乘除的数学运算功能
- Java简单的 整数加减乘除运算
- c++ 直接中缀表达式求值 仅支持正整数的四则混合运算
- 只用位运算来实现整数的加减乘除四则运算
- 正负整数求余运算
- ecshop dwt模版smarty支持加减乘除运算