ToB企服应用市场:ToB评测及商务社交产业平台

标题: 大数科学计算器 C++ [打印本页]

作者: 守听    时间: 2023-3-9 00:07
标题: 大数科学计算器 C++
大数计算器


目录

优点

实现思路

自定义类

运用C++ 类的封装  自定义了两个类: MyNum类 和 Method类
下面是这两个大类的简单归纳总结
MyNum类  ★★★

Method类

具体函数实现

MyNum类的函数

构造 & 三大函数
  1. //构造函数
  2.         MyNum(const std::deque<int>& d=ZERODEQUE,int p=0,int s=0)
  3.                 :digits(d),power(p),sign(s){}
  4.         MyNum(int i);
  5.         MyNum(long long i);
  6.         MyNum(double d);
  7.         MyNum(std::string str);
  8. //拷贝构造拷贝赋值
  9.         MyNum(const MyNum& other)
  10.                 :digits(other.digits), power(other.power),sign(other.sign) {}
  11.         MyNum& operator= (const MyNum& other) {
  12.                 this->digits = other.digits;
  13.                 this->power = other.power;
  14.                 this->sign = other.sign;
  15.                 return *this;
  16.         }
复制代码
都比较普通  能拿出来说的也就是从字符串string构造MyNum
总体思路:
源码:
  1. MyNum::MyNum(std::string str) {
  2.         if (str.size() && (str[0] < '0' || str[0]>'9')) {                //string不是数字是个计算符号
  3.                 if (!((str[0] == '-' || str[0] == '+') && str.size() > 1 && str[1] >= '0' && str[1] <= '9')) {
  4.                         this->sign = 2;
  5.                         if (str[0] >= 'a' && str[0] <= 'z' || str[0] >= 'A' && str[0] <= 'Z')         //函数类型计算  优先级4
  6.                                 power = 4;
  7.                         else {
  8.                                 if (str[0] == '(') power = -2;
  9.                                 if (str[0] == '=' || str[0] == '<' || str[0] == '>') power = 0;
  10.                                 if (str[0] == '+' || str[0] == '-') power = 1;
  11.                                 if (str[0] == '*' || str[0] == '/') power = 2;
  12.                                 if (str[0] == '^') power = 3;
  13.                                 if (str[0] == '%') power = 5;
  14.                                 if (str[0] == ',')        power = -1;                                //根据不同的符号 确定各自的优先级
  15.                         }
  16.                         for (int i = 0; i < str.size(); i++) {
  17.                                 this->digits.push_back(int(str[i]));                //将名字存进digits里面
  18.                         }
  19.                         return;
  20.                 }
  21.         }
  22.     //下面就是str表示的是数字情况
  23.         this->sign = 1;
  24.         int i = 0;
  25.         while (str[i] == ' ') i++;
  26.         if (str[i] == '-') {
  27.                 this->sign = -1; i++;
  28.         }
  29.         if (str[i] == '+') i++;
  30.         int retpower = 0;
  31.         bool startdigits = false;        //开始有效数字
  32.         int powerchange = 1;                //1表示每往后一格power++  -1就是小数情况
  33.         int ifdecimal = false;
  34.         bool ifmeetpoint = false;        //有无遇见小数点
  35.         while (i < str.size()) {
  36.                 if (startdigits && str[i]>='0' && str[i]<='9') {
  37.                         this->digits.push_back(str[i] - '0');
  38.                         if (!ifmeetpoint)
  39.                                 retpower++;
  40.                 }
  41.                 else {
  42.                         if (str[i] >= '1' && str[i] <= '9') {
  43.                                 startdigits = true;
  44.                                 this->digits.push_back(str[i] - '0');
  45.                                 if (!ifmeetpoint)
  46.                                         retpower++;
  47.                                 if (ifdecimal) {
  48.                                         this->power = retpower;
  49.                                 }
  50.                         }
  51.                         if (str[i] == '0' && ifdecimal) {
  52.                                 retpower--;
  53.                         }
  54.                         if (str[i] == '.') {
  55.                                 ifmeetpoint = true;
  56.                                 if (!startdigits) {        //小数
  57.                                         ifdecimal = true;
  58.                                 }
  59.                                 else {
  60.                                         this->power = retpower;
  61.                                 }
  62.                         }
  63.                 }
  64.                 i++;
  65.         }
  66.         while (!this->digits.empty() && this->digits.back() == 0)                //去除末尾的0 保证digits里是纯纯的有效数字
  67.                 this->digits.pop_back();
  68.         if (digits.empty()) {                //如果去掉0之后发现没东西了  那么说明这个数字就是0 返回ZERO零常量
  69.                 *this = ZERO;
  70.         }
  71.         this->power = retpower;
  72.         this->setPrecision();                //规定小数位数精度  毕竟无限小数不能有无限大的digits给你用
  73. }
复制代码
数学函数
  1. //数学函数
  2.         static MyNum getPI();        //求π
  3.   //单目数学函数
  4.         MyNum My_sqrt() const;
  5.         MyNum My_sin() const; MyNum My_cos() const; MyNum My_tan() const;
  6.         MyNum My_exp() const;
  7.         MyNum My_fabs() const;
  8.         MyNum My_neg() const;
  9.         MyNum My_log() const;
  10.   //多目数学函数
  11.         friend MyNum My_gcd(const MyNum& a, const MyNum& b);
  12.         friend MyNum My_lcm(const MyNum& a, const MyNum& b);
复制代码
其中值得拿出来说的一些函数是
转换函数
  1. //转换函数
  2.         double to_double() const;
  3.         int to_int() const;
  4.         long long to_longlong() const;
  5.         std::string to_string() const;
  6.         MyNum decimalpart() const;
  7.         MyNum addError(int i)const;
复制代码
正常的转换函数没啥好说的
要说的是里面最后一个addError()
给他一个参数i  i指的是要添加哪一种ERROR进去  什么叫哪一种ERROR?  在上文有说过 我们想要实现不同的错误类型的区分  所以就有了几个错误类型的划分 这里的i就是对应你要添加哪种错误类型
具体就是
如果是在原来ERROR的基础上添加一个新的错误类型  也就是要在digits的第i位置为1  那么先补全digits  然后置为1就好
源码:
  1. MyNum MyNum::addError(int i)const {
  2.         MyNum ret(ERROR);
  3.         ret.digits.clear();
  4.         if (this->sign == -2)
  5.                 ret = *this;
  6.         for (int temp = ret.digits.size(); temp <= i; temp++) {                //补全digits到i
  7.                 ret.digits.push_back(0);
  8.         }
  9.         ret.digits[i] = 1;
  10.         return ret;
  11. }
复制代码
最前面的部分是重载了一下ERROR+ERROR的情况  方便之后使用
-
减法跟加法大同小异 也是先对齐小数点然后逐位相减 然后从后往前处理 只是要注意一下处理完之后第一位被借没掉的情况  此时要变power
源码:
  1. //运算符重载
  2.         bool operator<(const MyNum& other)const;
  3.         bool operator>(const MyNum& other)const;
  4.         bool operator==(const MyNum& other)const;
  5.         bool operator!=(const MyNum& other)const;
  6.         bool operator<=(const MyNum& other)const;
  7.         bool operator>=(const MyNum& other)const;
  8.         MyNum operator+(const MyNum& other)const;
  9.         MyNum operator-()const;
  10.         MyNum operator-(const MyNum& other)const;
  11.         MyNum operator*(const MyNum& other)const;
  12.         MyNum operator/(const MyNum& other)const;
  13.         MyNum operator^(const MyNum& other)const;
  14.         MyNum power_int(int k)const;
  15.         MyNum power_decimal(const MyNum& decimal)const;
  16.         MyNum& operator+=(const MyNum& other);
  17.         MyNum& operator-=(const MyNum& other);
  18.         MyNum& operator*=(const MyNum& other);
  19.         MyNum& operator/=(const MyNum& other);
复制代码
*
还是列竖式  a的每一位数去乘b的每一位数  途中注意对齐问题  然后把所有的加起来 就是最终的结果 注意进位即可
  1. MyNum MyNum::operator+(const MyNum& other)const {
  2.         //ERROR
  3.         if ((*this).sign == -2 || other.sign == -2) {
  4.                 if ((*this).sign == -2 && other.sign == -2) {
  5.                         MyNum reterror(ERROR);
  6.                         for (int i = 0; i < this->digits.size(); i++) {
  7.                                 if (this->digits[i]) {
  8.                                         reterror = reterror.addError(i);
  9.                                 }
  10.                         }
  11.                         for (int i = 0; i < other.digits.size(); i++) {
  12.                                 if (other.digits[i]) {
  13.                                         reterror = reterror.addError(i);
  14.                                 }
  15.                         }
  16.                         return reterror;
  17.                 }
  18.                 if ((*this).sign == -2) return *this;
  19.                 if (other.sign == -2) return other;
  20.         }
  21.         //异号
  22.         if (this->sign * other.sign == -1) {
  23.                 if (this->sign < 0) return other - (-(*this));
  24.                 else return (*this) - (-other);
  25.         }
  26.         //0
  27.         if (this->sign == 0) return other;
  28.         if (other.sign == 0) return *this;
  29.         //同号
  30.         //找到较大的那个数 用它加上较小的数 比较省事
  31.         MyNum const *bigger,*smaller;
  32.         if (this->My_fabs() >= other.My_fabs())
  33.                 { bigger = this; smaller = &other; }
  34.         else
  35.                 { bigger = &other; smaller = this; }
  36.         int retpower = bigger->power;
  37.         int retsign = bigger->sign;
  38.         //对齐小数点后逐位相加
  39.         int diff = bigger->power - smaller->power;                //小数点偏差
  40.         std::deque<int> retdigits = bigger->digits;
  41.         int length = 0;
  42.         while (length < diff) {
  43.                 while (length >= retdigits.size())
  44.                         retdigits.push_back(0);
  45.                 length++;
  46.         }
  47.         for (int temp = 0; temp < smaller->digits.size(); temp++) {
  48.                 while (length >= retdigits.size())
  49.                         retdigits.push_back(0);
  50.                 retdigits[length++] += smaller->digits[temp];
  51.         }
  52.         //从后往前逐位校准
  53.         for (int temp = length - 1; temp >= 1; temp--) {
  54.                 retdigits[temp - 1] += retdigits[temp] / 10;
  55.                 retdigits[temp] %= 10;
  56.         }
  57.         if (retdigits[0] >= 10) {
  58.                 retdigits.push_front(retdigits[0] / 10);
  59.                 retdigits[1] %= 10;
  60.                 retpower++;
  61.         }
  62.         //末尾去0
  63.         while (!retdigits.empty() && retdigits.back() == 0)
  64.                 retdigits.pop_back();
  65.         if (retdigits.empty()) return ZERO;
  66.         MyNum ans(retdigits, retpower, retsign);
  67.         ans.setPrecision();
  68.         return ans;
  69. }
复制代码
/
除法算是比较难想的一个了 他也是列竖式 但是除法竖式本身就和之前的三种不一样  所以不是很容易
也是除数一位位往右边挪  一步步翻倍除数  一直到他大于被除数 这个时候翻了几倍就是这个位数的答案 接着把除数往后挪一格  重复以上过程
  1. MyNum MyNum::operator-(const MyNum& other)const {
  2.         //ERROR
  3.         if ((*this).sign == -2 || other.sign == -2) return *this+other;
  4.         //异号
  5.         if (this->sign * other.sign == -1) {
  6.                 if (this->sign < 0) return -(other + (-(*this)));
  7.                 else return (*this) + (-other);
  8.         }
  9.         //0
  10.         if (this->sign == 0) return -other;
  11.         if (other.sign == 0) return -(*this);
  12.         //同号
  13.         if ((*this) == other) return ZERO;
  14.         int retsign;
  15.         //找到绝对值较大的那个数 用它减去较小的数 比较省事
  16.         MyNum const *bigger, *smaller;
  17.         if (this->My_fabs() > other.My_fabs())
  18.                 { bigger = this; smaller = &other; retsign = bigger->sign; }
  19.         else
  20.                 { bigger = &other; smaller = this; retsign = -bigger->sign; }
  21.         int retpower = bigger->power;
  22.         //对齐小数点逐位相减
  23.         int diff = bigger->power - smaller->power;                //小数点偏差
  24.         std::deque<int> retdigits = bigger->digits;
  25.         int length = 0;
  26.         while (length < diff) {
  27.                 while (length >= retdigits.size())
  28.                         retdigits.push_back(0);
  29.                 length++;
  30.         }
  31.         for (int temp = 0; temp < smaller->digits.size(); temp++) {
  32.                 while (length >= retdigits.size())
  33.                         retdigits.push_back(0);
  34.                 retdigits[length++] -= smaller->digits[temp];
  35.         }
  36.         //从后往前逐位校准
  37.         for (int temp = length - 1; temp >= 1; temp--) {
  38.                 while (retdigits[temp] < 0) {
  39.                         retdigits[temp - 1]--;
  40.                         retdigits[temp] += 10;
  41.                 }
  42.         }
  43.         //去头0 去尾0
  44.         while (!retdigits.empty() && retdigits.front() == 0) {
  45.                 retdigits.pop_front();
  46.                 retpower--;
  47.         }
  48.         while (!retdigits.empty() && retdigits.back() == 0)
  49.                 retdigits.pop_back();
  50.         if (retdigits.empty()) return ZERO;
  51.         MyNum ans(retdigits, retpower, retsign);
  52.         ans.setPrecision();
  53.         return ans;
  54. }
复制代码
^
之前提过了  这些个运算里面最最有含金量的就是乘方运算  因为他实现了小数指数的计算
大致思路就是把小数指数 拆成整数和小数部分  其中整数部分操作的时候利用快速幂来进行优化  小数部分利用log()函数以及泰勒展开的技巧 迭代求出最后结果  两部分求出来之后最后乘到一起就是最终的结果
源码:
  1. MyNum MyNum::operator*(const MyNum& other)const {
  2.         //ERROR
  3.         if ((*this).sign == -2 || other.sign == -2) return *this + other;
  4.         //0
  5.         if (this->sign == 0) return ZERO;
  6.         if (other.sign == 0) return ZERO;
  7.         int retsign = this->sign * other.sign;
  8.         int retpower = this->power + other.power;
  9.         std::deque<int> retdigits;
  10.         for (int i = 0; i < this->digits.size(); i++) {
  11.                 if (this->digits[i] == 0) continue;
  12.                 int temp = i;
  13.                 for (int j = 0; j < other.digits.size(); j++) {
  14.                         while (temp >= retdigits.size())
  15.                                 retdigits.push_back(0);
  16.                         retdigits[temp++] += this->digits[i] * other.digits[j];
  17.                 }
  18.         }
  19.         for (int temp = retdigits.size() - 1; temp >= 1; temp--) {
  20.                 retdigits[temp - 1] += retdigits[temp] / 10;
  21.                 retdigits[temp] %= 10;
  22.         }
  23.         retpower--;
  24.         while (retdigits.front() >= 10) {
  25.                 retdigits.push_front(retdigits[0] / 10);
  26.                 retdigits[1] %= 10;
  27.                 retpower++;
  28.         }
  29.         MyNum ans(retdigits, retpower, retsign);
  30.         ans.setPrecision();
  31.         return ans;
  32. }
复制代码
这个还是挺有含金量的
</ul>显示函数
  1. MyNum MyNum::operator/(const MyNum& other)const {
  2.         //ERROR
  3.         if ((*this).sign == -2 || other.sign == -2) return *this + other;
  4.         //除0
  5.         if (other.sign == 0) {
  6.                 return ERROR.addError(0);
  7.         }
  8.         if (this->sign == 0) {
  9.                 return ZERO;
  10.         }
  11.         if (other == MyNum(1)) return *this;
  12.         if (other == MyNum(-1)) return -*this;
  13.         int retsign = this->sign * other.sign;
  14.         int retpower = this->power - other.power;
  15.         std::deque<int> a = this->digits;
  16.         std::deque<int> b = other.digits;
  17.         std::deque<int> ans;
  18.         for (int temp = 0; temp <= PRECISION + retsign; temp++) {                //除法核心部分
  19.                 int next = 0;
  20.                 while (cmp_digits(a, b) > 0) {
  21.                         minus_digits(a, b);
  22.                         next++;
  23.                 }
  24.                 if (cmp_digits(a, b) == 0) {
  25.                         next++;
  26.                         ans.push_back(next);
  27.                         break;
  28.                 }
  29.                 ans.push_back(next);
  30.                 b.push_front(0);
  31.         }
  32.         while (!ans.empty() && ans.front() == 0) {
  33.                 ans.pop_front();
  34.                 retpower--;
  35.         }
  36.         while (!ans.empty() && ans.back() == 0) {
  37.                 ans.pop_back();
  38.         }
  39.         retpower++;
  40.         MyNum ret(ans, retpower, retsign);
  41.         ret.setPrecision();
  42.         return ret;
  43. }
复制代码
都没啥好说的
show()里面有个显示ERROR内容  大致就是有一个存放各个error名字的数组  如果这个MyNum是ERROR  那么就根据他的digits去看对应了哪一种的ERROR  然后输出就行
源码:
  1. MyNum MyNum::operator^(const MyNum& other) const{
  2.         //ERROR
  3.         if ((*this).sign == -2 || other.sign == -2) return *this + other;
  4.         MyNum b(other);
  5.         if (b.sign == 0) return (this->sign == 0) ? ERROR.addError(1) : ZERO;
  6.         if (this->sign == 0) return (b.sign > 0) ? ZERO : ERROR.addError(0);
  7.         //仅排除了底数为零的情况 不保证幂指数的整数部分和小数部分不为0
  8.         if (b.sign > 0)
  9.                 return power_int(other.to_int()) * (power_decimal(other.decimalpart()));        //整数部分快速幂 小数部分泰勒展开
  10.         else
  11.                 return MyNum(1) / (power_int(-other.to_int()) * (power_decimal(-other.decimalpart())));
  12. }
  13. MyNum MyNum::power_int(int k)const {                //整数部分
  14.         if (k == 0) return MyNum(1);
  15.         if (k < 0) return MyNum(1) / ((*this) ^ (-k));
  16.         if (*this == MyNum(1)) return MyNum(1);
  17.        
  18.         //快速幂部分
  19.         MyNum ans(1);
  20.         MyNum bottom(*this);
  21.         while (k) {
  22.                 if (k & 1) {
  23.                         ans *= bottom;
  24.                 }
  25.                 bottom *= bottom;
  26.                 k >>= 1;
  27.         }
  28.         ans.setPrecision();
  29.         return ans;
  30. }       
  31. MyNum MyNum::power_decimal(const MyNum& decimal) const{                //小数部分
  32.         //ERROR
  33.         if ((*this).sign == -2) return *this;
  34.        
  35.         if (decimal.sign == 0) return MyNum(1);
  36.         if (this->sign < 0)        //底数负数 不可进行小数幂
  37.                 return ERROR.addError(2);
  38.         MyNum mult = this->My_log() * decimal;        //泰勒展开每一项要乘的东西
  39.         MyNum add(1);
  40.         MyNum ret;
  41.         for (int i = 1; add.sign != 0; i++) {
  42.                 ret += add;
  43.                 add = add * mult / MyNum(i);
  44.         }
  45.         return ret;
  46. }
复制代码
Method类的函数

构造函数
  1. //显示
  2.         void show() const;
  3.         void setPrecision(int prec = PRECISION);
复制代码
无要说的  就是正常的构造
操作函数
  1. void MyNum::show() const {
  2.         if (this->sign==-2) {
  3.                 printf("ERROR\n");
  4.                 for (int i = 0; i < digits.size(); i++) {
  5.                         if (digits[i])
  6.                                 std::cout << errorreason[i] << std::endl;
  7.                 }
  8.                 return;
  9.         }
  10.         if (sign == 2) {
  11.                 if (digits[0] == ',') return;
  12.                 for (int i = 0; i < digits.size(); i++)
  13.                         printf("%c", char(digits[i]));
  14.                 return;
  15.         }
  16.         int power = this->power;
  17.         int sign = this->sign;
  18.         std::deque<int> digits = this->digits;
  19.         if (sign == -1) printf("-");
  20.         if (sign == 0) { printf("0"); return; }
  21.         if (power <= 0) {
  22.                 printf("0.");
  23.                 while (power < 0) {
  24.                         printf("0"); power++;
  25.                 }
  26.                 power--;
  27.         }
  28.         for (int i = 0; i < digits.size(); i++) {
  29.                 if (power-- == 0) {
  30.                         printf(".");
  31.                 }
  32.                 printf("%d", digits[i]);
  33.         }
  34.         while (power > 0) {
  35.                 printf("0");
  36.                 power--;
  37.         }
  38. }
复制代码
重中之重就是一个把原计算式转换为后缀表达式的changetorpn()  还有一个计算函数calculate()
<ul>changetorpn()
简单思路: 通过遍历calstr计算式子字符串  把每个对应于数字的 对应于计算符号的  对应于计算函数的 全部一个个拆开来分成单独的MyNum 然后根据后缀表达式的转换规则  利用一个操作符单调栈opstack 按照操作符优先级的严格递增顺序进行入栈出栈 也就是严格单调栈  从而进行后缀表达式的转换
具体可以参见这篇文章: https://blog.csdn.net/a8425/article/details/119253258
源码:
  1. void Method::changetorpn() {        this->rpn.clear();        std::deque& retrpn = this->rpn;        std::deque opstack;        //符号栈(用deque模拟栈)        string nowdigits;        string op;        for (int i = 0; i < calstr.size(); i++) {                if (calstr[i] == ' ') continue;                if (calstr[i] == ',') {                        if (!nowdigits.empty()) {                                retrpn.push_back(MyNum(nowdigits));                                nowdigits.clear();                        }                        while (!opstack.empty() && opstack.back() != MyNum("(")) {                                retrpn.push_back(opstack.back());                                opstack.pop_back();                        }                        //opstack.pop_back();                        continue;                }                if (calstr[i] == '-' ) {                        if (!(!nowdigits.empty() || i > 0 && calstr[i - 1] == ')')) {        //'-'是负号不是减号                                if (!op.empty()) {                                        opstackpushback(opstack, MyNum(op));                                        op.clear();                                }                                opstackpushback(opstack, MyNum("neg"));                                continue;                        }                }                if (calstr[i] >= '0' && calstr[i]  12 && str.substr(0,12) == "setprecision") {                int newprecision = 0;                for (int i = 13; i < str.size(); i++) {                        newprecision *= 10;                        newprecision += str[i] - '0';                }                SHOW_PRECISION = newprecision;                return 4;        }        Method m(str);        history.push_back(m);        return 1;}void Func() {        int input = 1;        while(true) {                input = inputMethod();                if (input == 0) break;                if (input == 1) {                        history.back().show(showType);                        cout digits = other.digits;                this->power = other.power;                this->sign = other.sign;                return *this;        }        //析构        ~MyNum() {}        //数学函数        static MyNum getPI();        //求π        //单目数学函数        MyNum My_sqrt() const;        MyNum My_sin() const; MyNum My_cos() const; MyNum My_tan() const;        MyNum My_exp() const;        MyNum My_fabs() const;        MyNum My_neg() const;         MyNum My_log() const;        //多目数学函数                //见类外定义的非成员函数        friend MyNum My_gcd(const MyNum& a, const MyNum& b);        friend MyNum My_lcm(const MyNum& a, const MyNum& b);        //转换函数
  2.         double to_double() const;
  3.         int to_int() const;
  4.         long long to_longlong() const;
  5.         std::string to_string() const;
  6.         MyNum decimalpart() const;
  7.         MyNum addError(int i)const;        //运算符重载        bool operator(const MyNum& other)const;        bool operator==(const MyNum& other)const;        bool operator!=(const MyNum& other)const;        bool operator=(const MyNum& other)const;        MyNum operator+(const MyNum& other)const;        MyNum operator-()const;        MyNum operator-(const MyNum& other)const;        MyNum operator*(const MyNum& other)const;        MyNum operator/(const MyNum& other)const;        MyNum operator^(const MyNum& other)const;        MyNum power_int(int k)const;        MyNum power_decimal(const MyNum& decimal)const;        MyNum& operator+=(const MyNum& other);        MyNum& operator-=(const MyNum& other);        MyNum& operator*=(const MyNum& other);        MyNum& operator/=(const MyNum& other);        MyNum MyNum::operator/(const MyNum& other)const {
  8.         //ERROR
  9.         if ((*this).sign == -2 || other.sign == -2) return *this + other;
  10.         //除0
  11.         if (other.sign == 0) {
  12.                 return ERROR.addError(0);
  13.         }
  14.         if (this->sign == 0) {
  15.                 return ZERO;
  16.         }
  17.         if (other == MyNum(1)) return *this;
  18.         if (other == MyNum(-1)) return -*this;
  19.         int retsign = this->sign * other.sign;
  20.         int retpower = this->power - other.power;
  21.         std::deque<int> a = this->digits;
  22.         std::deque<int> b = other.digits;
  23.         std::deque<int> ans;
  24.         for (int temp = 0; temp <= PRECISION + retsign; temp++) {                //除法核心部分
  25.                 int next = 0;
  26.                 while (cmp_digits(a, b) > 0) {
  27.                         minus_digits(a, b);
  28.                         next++;
  29.                 }
  30.                 if (cmp_digits(a, b) == 0) {
  31.                         next++;
  32.                         ans.push_back(next);
  33.                         break;
  34.                 }
  35.                 ans.push_back(next);
  36.                 b.push_front(0);
  37.         }
  38.         while (!ans.empty() && ans.front() == 0) {
  39.                 ans.pop_front();
  40.                 retpower--;
  41.         }
  42.         while (!ans.empty() && ans.back() == 0) {
  43.                 ans.pop_back();
  44.         }
  45.         retpower++;
  46.         MyNum ret(ans, retpower, retsign);
  47.         ret.setPrecision();
  48.         return ret;
  49. }private:        std::deque digits;        int power;        int sign;        friend class Method;};MyNum My_gcd(const MyNum& a, const MyNum& b);MyNum My_lcm(const MyNum& a, const MyNum& b);#endif
复制代码
MyNum.cpp
  1. #define _CRT_SECURE_NO_WARNINGS#include "MyNum.h"#include #include #define ZERO_LIMIT 1e-6                //小于这个数字的浮点数 就判定为0#define TAYLOR_LIMIT 50                //数学函数里面使用泰勒展开的数据最大值 因为数据过大泰勒展开将会耗时过久extern const MyNum ZERO({ 0 }, 0, 0);extern const MyNum ERROR({}, 0, -2);extern const MyNum ONE(1);//const MyNum PI(MyNum::getPI());extern MyNum PI("3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446");                                //运用getPI函数将会超时... 因此直接读入pi会更好extern MyNum PIDOUBLE("6.2831853071795864769252867665590057683943387987502116419498891846156328125724179972560696506842341359642961730265646132941876892");//工具函数int getmin(int a, int b) { return a < b ? a : b; }int getmax(int a, int b) { return a > b ? a : b; }int inttodeque(std::deque& digits, int i) {        if (i == 0) {                digits.push_back(0);                return 0;        }        int retpower = 0;        i = i > 0 ? i : -i;        while (i) {                digits.push_front(i % 10);                i /= 10;                retpower++;        }        return retpower;}int cmp_digits(std::deque& a, std::deque& b) {        for (int i = 0; i < getmin(a.size(), b.size());i++) {                if (a[i] > b[i]) return 1;                if (a[i] < b[i]) return -1;        }        if (a.size() > b.size()) return 1;        if (a.size() < b.size()) return -1;        return 0;}int minus_digits(std::deque& a, std::deque& b) {        //前提确保了a>b        for (int i = 0; i < b.size(); i++) {                if (i == a.size())                        a.push_back(0);                a[i] -= b[i];        }        for (int i = a.size() - 1; i >= 1; i--) {                while (a[i] < 0) {                        a[i - 1] --;                        a[i] += 10;                }        }        int ret = 0;        //返回借位        while (a[0] < 0) {                ret++;                a[0]+=10;        }        return ret;}string digittostring(std::deque& digits) {                        string ans;        for (int i = 0; i < digits.size(); i++) {                ans.push_back(char(digits[i]));        }        return ans;}//构造函数MyNum::MyNum(int i) {        *this = MyNum((long long)i);}MyNum::MyNum(long long i) {        if (i == 0ll) {                *this = ZERO;                return;        }        int power = 0;        std::deque digits;        int sign = 1;        if (i < 0) sign = -1;        i *= sign;        while (i) {                digits.push_front(i % 10);                i /= 10;                power++;        }        while (digits.back() == 0)                digits.pop_back();        this->digits = digits;        this->power = power;        this->sign = sign;}MyNum::MyNum(double d) {        if (d < ZERO_LIMIT && d>-ZERO_LIMIT) {                *this = ZERO;                return;        }        this->sign = (d > 0) ? 1 : -1;        d *= sign;        int retpower = 0;        if(int(d)!=0)                 retpower = inttodeque(this->digits, int(d));        bool ifFindDemicalPoint = retpower >= 0;        //是否找到小数点        d -= int(d);        //只保留小数部分        while (d > ZERO_LIMIT || d < -ZERO_LIMIT) {                d *= 10;                int integer = int(d);                d -= integer;                if (ifFindDemicalPoint)                        this->digits.push_back(integer);                else {                        if (integer == 0)                                 retpower--;                        else                                 ifFindDemicalPoint = true;                }        }        this->power = retpower;        while (this->digits.back() == 0)                 this->digits.pop_back();        this->setPrecision();        /*char str[1000];        sprintf(str, "%lf", d);        *this = MyNum(std::string(str));*/                //sprintf转换成字符串只有6位小数的精度}MyNum::MyNum(std::string str) {        if (str.size() && (str[0] < '0' || str[0]>'9')) {                if (!((str[0] == '-' || str[0] == '+') && str.size() > 1 && str[1] >= '0' && str[1] sign = 2;                        if (str[0] >= 'a' && str[0] = 'A' && str[0] digits.push_back(int(str[i]));                        }                        return;                }        }        this->sign = 1;        int i = 0;        while (str[i] == ' ') i++;        if (str[i] == '-') {                this->sign = -1; i++;        }        if (str[i] == '+') i++;        int retpower = 0;        bool startdigits = false;        //开始有效数字        int powerchange = 1;                //1表示每往后一格power++  -1就是小数情况        int ifdecimal = false;        bool ifmeetpoint = false;        //有无遇见小数点        while (i < str.size()) {                if (startdigits && str[i]>='0' && str[i]digits.push_back(str[i] - '0');                        if (!ifmeetpoint)                                 retpower++;                }                else {                        if (str[i] >= '1' && str[i] digits.push_back(str[i] - '0');                                if (!ifmeetpoint)                                        retpower++;                                if (ifdecimal) {                                        this->power = retpower;                                }                        }                        if (str[i] == '0' && ifdecimal) {                                retpower--;                        }                        if (str[i] == '.') {                                ifmeetpoint = true;                                if (!startdigits) {        //小数                                        ifdecimal = true;                                }                                else {                                        this->power = retpower;                                }                        }                }                i++;        }        while (!this->digits.empty() && this->digits.back() == 0)                this->digits.pop_back();        if (digits.empty()) {                *this = ZERO;        }        this->power = retpower;        this->setPrecision();}//数学函数MyNum MyNum::getPI() {                MyNum ret;        MyNum add(1);        for (int i = 1; add.sign != 0; i+=2) {                add = ONE / MyNum(i);                if ((i / 2) % 2)                        ret -= add;                else                        ret += add;        }        return ret*MyNum(4);}//单目数学函数MyNum MyNum::My_sqrt() const {        //return *this^MyNum(0.5);        return MyNum(sqrt(this->to_double()));}MyNum MyNum::My_sin() const {        if (this->sign == 0) return ZERO;        MyNum cal(*this);        while (cal < -PIDOUBLE)                cal += PIDOUBLE;        while (cal > PIDOUBLE)                 cal -= PIDOUBLE;        //PI优化        MyNum ret;        MyNum add(-1);        for (int i = 1; add.sign != 0; i++) {                add = add * cal / MyNum(i);                if (i % 2) {                        add.sign *= -1;                        ret += add;                }        }        return ret;}MyNum MyNum::My_cos() const{         if (this->sign == 0) return MyNum(1);        MyNum cal(*this);        while (cal < -PIDOUBLE)                cal += PIDOUBLE;        while (cal > PIDOUBLE)                cal -= PIDOUBLE;        //PI优化        MyNum ret(1);        MyNum add(1);        for (int i = 1; add.sign != 0; i++) {                add = add * cal / MyNum(i);                if (i % 2 == 0) {                        add.sign *= -1;                        ret += add;                }        }        return ret;}MyNum MyNum::My_tan() const{         return this->My_sin() / this->My_cos();}MyNum MyNum::My_exp() const {         if (this->sign == 0) return ONE;        if(*this>MyNum(TAYLOR_LIMIT))                return MyNum(exp(this->to_double()));        MyNum ret;        MyNum add(1);        for (int i = 1; add.sign != 0; i++) {                ret += add;                add *= (*this) / MyNum(i);        }        return ret;}MyNum MyNum::My_fabs() const {        return MyNum(this->digits, this->power, (this->signsign addError(4);        }        return MyNum(log(this->to_double()));}//多目数学函数MyNum My_gcd_recursion(MyNum& a, MyNum& b) {        //递归辗转相除        while (a > b) {                a -= b;        }        if (a == b)                 return a;        else                 return My_gcd_recursion(b, a);}MyNum My_gcd(const MyNum& a,const MyNum& b) {        if (a.sign != b.sign) return ERROR;        MyNum aa(a.digits,a.power,1),bb(b.digits,b.power,1);        MyNum ret(My_gcd_recursion(aa, bb));        ret.sign = a.sign;        return ret;}MyNum My_lcm(const MyNum& a,const MyNum& b) {        return a * b / My_gcd(a, b);}//转换函数double MyNum::to_double() const {        double ret = 0;        const std::deque& digits=this->digits;        for (int i = digits.size() - 1; i >= 0; i--) {        //化为类科学计数法 0.xxx                ret += digits[i];                ret /= 10;        }        if(this->power>0)                for (int i = 0; i < this->power; i++)                        ret *= 10;        else {                for (int i = 0; i < -this->power; i++) {                        ret /= 10;                }        }        return ret;}int MyNum::to_int() const {        if (power digits[i];        }        return ret * this->sign;}long long MyNum::to_longlong() const {        if (power digits[i]);        }        return ret * this->sign;}std::string MyNum::to_string() const {        if (sign == -2) return "ERROR";        if (sign == 0) return "0";        string ans;        if (sign == -1) ans.push_back('-');        int power = this->power;        const std::deque& digits = this->digits;        if (power = digits.size())                                ans.push_back('0');                        else                                ans.push_back('0' + digits[i]);                }                if (i < digits.size()) {                        ans.push_back('.');                        for (; i < digits.size(); i++) {                                ans.push_back(digits[i]);                        }                }        }        return ans;}MyNum MyNum::decimalpart() const {        if (this->power sign == -2)                ret = *this;        for (int temp = ret.digits.size(); temp sign > other.sign) return false;        //下面同号情况        if (this->power < other.power) return sign == 1;        //绝对值小 判断是否正数        if (this->power > other.power) return sign == -1;        //绝对值小 判断是否正数        //同号 指数相同 比较有效数字        int i;        for (i = 0; i < getmin(this->digits.size(), other.digits.size()); i++) {                if (this->digits[i] < other.digits[i]) return sign == 1;                if (this->digits[i] > other.digits[i]) return sign == -1;        }        //有效数字重叠  判断哪个短        if (this->digits.size() < other.digits.size()) return sign == 1;        if (this->digits.size() > other.digits.size()) return sign == -1;        return false;}bool MyNum::operator>(const MyNum& other)const {        if (this->sign > other.sign) return true;        if (this->sign < other.sign) return false;        //下面同号情况        if (this->power > other.power) return sign == 1;        //绝对值大 判断是否正数        if (this->power < other.power) return sign == -1;        //同号 指数相同 比较有效数字        int i;        for (i = 0; i < getmin(this->digits.size(), other.digits.size()); i++) {                if (this->digits[i] > other.digits[i]) return sign == 1;                if (this->digits[i] < other.digits[i]) return sign == -1;        }        //有效数字重叠  判断哪个长        if (this->digits.size() > other.digits.size()) return sign == 1;        if (this->digits.size() < other.digits.size()) return sign == -1;        return false;}bool MyNum::operator==(const MyNum& other)const {        return (this->digits == other.digits && this->sign == other.sign && this->power == other.power);}bool MyNum::operator!=(const MyNum& other)const {        return !(this->operator==(other));}bool MyNum::operator=(const MyNum& other)const {        return (*this) > other || (*this) == other;}MyNum MyNum::operator+(const MyNum& other)const {        //ERROR        if ((*this).sign == -2 || other.sign == -2) {                if ((*this).sign == -2 && other.sign == -2) {                        MyNum reterror(ERROR);                        for (int i = 0; i < this->digits.size(); i++) {                                if (this->digits[i]) {                                        reterror = reterror.addError(i);                                }                        }                        for (int i = 0; i < other.digits.size(); i++) {                                if (other.digits[i]) {                                        reterror = reterror.addError(i);                                }                        }                        return reterror;                }                if ((*this).sign == -2) return *this;                if (other.sign == -2) return other;        }        //异号        if (this->sign * other.sign == -1) {                if (this->sign < 0) return other - (-(*this));                else return (*this) - (-other);        }        //0        if (this->sign == 0) return other;        if (other.sign == 0) return *this;        //同号        //找到较大的那个数 用它加上较小的数 比较省事        MyNum const *bigger,*smaller;        if (this->My_fabs() >= other.My_fabs())                 { bigger = this; smaller = &other; }        else                { bigger = &other; smaller = this; }        int retpower = bigger->power;        int retsign = bigger->sign;        //对齐小数点后逐位相加        int diff = bigger->power - smaller->power;                //小数点偏差        std::deque retdigits = bigger->digits;        int length = 0;        while (length < diff) {                while (length >= retdigits.size())                        retdigits.push_back(0);                length++;        }        for (int temp = 0; temp < smaller->digits.size(); temp++) {                while (length >= retdigits.size())                        retdigits.push_back(0);                retdigits[length++] += smaller->digits[temp];        }        //从后往前逐位校准        for (int temp = length - 1; temp >= 1; temp--) {                retdigits[temp - 1] += retdigits[temp] / 10;                retdigits[temp] %= 10;        }        if (retdigits[0] >= 10) {                retdigits.push_front(retdigits[0] / 10);                retdigits[1] %= 10;                retpower++;        }        //末尾去0        while (!retdigits.empty() && retdigits.back() == 0)                retdigits.pop_back();        if (retdigits.empty()) return ZERO;        MyNum ans(retdigits, retpower, retsign);        ans.setPrecision();        return ans;}MyNum MyNum::operator-()const {        return MyNum(this->digits, this->power, -(this->sign));}//运算符重载
  2.         bool operator<(const MyNum& other)const;
  3.         bool operator>(const MyNum& other)const;
  4.         bool operator==(const MyNum& other)const;
  5.         bool operator!=(const MyNum& other)const;
  6.         bool operator<=(const MyNum& other)const;
  7.         bool operator>=(const MyNum& other)const;
  8.         MyNum operator+(const MyNum& other)const;
  9.         MyNum operator-()const;
  10.         MyNum operator-(const MyNum& other)const;
  11.         MyNum operator*(const MyNum& other)const;
  12.         MyNum operator/(const MyNum& other)const;
  13.         MyNum operator^(const MyNum& other)const;
  14.         MyNum power_int(int k)const;
  15.         MyNum power_decimal(const MyNum& decimal)const;
  16.         MyNum& operator+=(const MyNum& other);
  17.         MyNum& operator-=(const MyNum& other);
  18.         MyNum& operator*=(const MyNum& other);
  19.         MyNum& operator/=(const MyNum& other);MyNum MyNum::operator+(const MyNum& other)const {
  20.         //ERROR
  21.         if ((*this).sign == -2 || other.sign == -2) {
  22.                 if ((*this).sign == -2 && other.sign == -2) {
  23.                         MyNum reterror(ERROR);
  24.                         for (int i = 0; i < this->digits.size(); i++) {
  25.                                 if (this->digits[i]) {
  26.                                         reterror = reterror.addError(i);
  27.                                 }
  28.                         }
  29.                         for (int i = 0; i < other.digits.size(); i++) {
  30.                                 if (other.digits[i]) {
  31.                                         reterror = reterror.addError(i);
  32.                                 }
  33.                         }
  34.                         return reterror;
  35.                 }
  36.                 if ((*this).sign == -2) return *this;
  37.                 if (other.sign == -2) return other;
  38.         }
  39.         //异号
  40.         if (this->sign * other.sign == -1) {
  41.                 if (this->sign < 0) return other - (-(*this));
  42.                 else return (*this) - (-other);
  43.         }
  44.         //0
  45.         if (this->sign == 0) return other;
  46.         if (other.sign == 0) return *this;
  47.         //同号
  48.         //找到较大的那个数 用它加上较小的数 比较省事
  49.         MyNum const *bigger,*smaller;
  50.         if (this->My_fabs() >= other.My_fabs())
  51.                 { bigger = this; smaller = &other; }
  52.         else
  53.                 { bigger = &other; smaller = this; }
  54.         int retpower = bigger->power;
  55.         int retsign = bigger->sign;
  56.         //对齐小数点后逐位相加
  57.         int diff = bigger->power - smaller->power;                //小数点偏差
  58.         std::deque<int> retdigits = bigger->digits;
  59.         int length = 0;
  60.         while (length < diff) {
  61.                 while (length >= retdigits.size())
  62.                         retdigits.push_back(0);
  63.                 length++;
  64.         }
  65.         for (int temp = 0; temp < smaller->digits.size(); temp++) {
  66.                 while (length >= retdigits.size())
  67.                         retdigits.push_back(0);
  68.                 retdigits[length++] += smaller->digits[temp];
  69.         }
  70.         //从后往前逐位校准
  71.         for (int temp = length - 1; temp >= 1; temp--) {
  72.                 retdigits[temp - 1] += retdigits[temp] / 10;
  73.                 retdigits[temp] %= 10;
  74.         }
  75.         if (retdigits[0] >= 10) {
  76.                 retdigits.push_front(retdigits[0] / 10);
  77.                 retdigits[1] %= 10;
  78.                 retpower++;
  79.         }
  80.         //末尾去0
  81.         while (!retdigits.empty() && retdigits.back() == 0)
  82.                 retdigits.pop_back();
  83.         if (retdigits.empty()) return ZERO;
  84.         MyNum ans(retdigits, retpower, retsign);
  85.         ans.setPrecision();
  86.         return ans;
  87. }MyNum MyNum::operator-(const MyNum& other)const {
  88.         //ERROR
  89.         if ((*this).sign == -2 || other.sign == -2) return *this+other;
  90.         //异号
  91.         if (this->sign * other.sign == -1) {
  92.                 if (this->sign < 0) return -(other + (-(*this)));
  93.                 else return (*this) + (-other);
  94.         }
  95.         //0
  96.         if (this->sign == 0) return -other;
  97.         if (other.sign == 0) return -(*this);
  98.         //同号
  99.         if ((*this) == other) return ZERO;
  100.         int retsign;
  101.         //找到绝对值较大的那个数 用它减去较小的数 比较省事
  102.         MyNum const *bigger, *smaller;
  103.         if (this->My_fabs() > other.My_fabs())
  104.                 { bigger = this; smaller = &other; retsign = bigger->sign; }
  105.         else
  106.                 { bigger = &other; smaller = this; retsign = -bigger->sign; }
  107.         int retpower = bigger->power;
  108.         //对齐小数点逐位相减
  109.         int diff = bigger->power - smaller->power;                //小数点偏差
  110.         std::deque<int> retdigits = bigger->digits;
  111.         int length = 0;
  112.         while (length < diff) {
  113.                 while (length >= retdigits.size())
  114.                         retdigits.push_back(0);
  115.                 length++;
  116.         }
  117.         for (int temp = 0; temp < smaller->digits.size(); temp++) {
  118.                 while (length >= retdigits.size())
  119.                         retdigits.push_back(0);
  120.                 retdigits[length++] -= smaller->digits[temp];
  121.         }
  122.         //从后往前逐位校准
  123.         for (int temp = length - 1; temp >= 1; temp--) {
  124.                 while (retdigits[temp] < 0) {
  125.                         retdigits[temp - 1]--;
  126.                         retdigits[temp] += 10;
  127.                 }
  128.         }
  129.         //去头0 去尾0
  130.         while (!retdigits.empty() && retdigits.front() == 0) {
  131.                 retdigits.pop_front();
  132.                 retpower--;
  133.         }
  134.         while (!retdigits.empty() && retdigits.back() == 0)
  135.                 retdigits.pop_back();
  136.         if (retdigits.empty()) return ZERO;
  137.         MyNum ans(retdigits, retpower, retsign);
  138.         ans.setPrecision();
  139.         return ans;
  140. }MyNum MyNum::operator^(const MyNum& other) const{        //ERROR        if ((*this).sign == -2 || other.sign == -2) return *this + other;        MyNum b(other);        if (b.sign == 0) return (this->sign == 0) ? ERROR.addError(1) : ZERO;        if (this->sign == 0) return (b.sign > 0) ? ZERO : ERROR.addError(0);        //仅排除了底数为零的情况 不保证幂指数的整数部分和小数部分不为0        if (b.sign > 0)                return power_int(other.to_int()) * (power_decimal(other.decimalpart()));        //整数部分快速幂 小数部分泰勒展开        else                return MyNum(1) / (power_int(-other.to_int()) * (power_decimal(-other.decimalpart())));}MyNum MyNum::power_int(int k)const {                if (k == 0) return MyNum(1);        if (k < 0) return MyNum(1) / ((*this) ^ (-k));        if (*this == MyNum(1)) return MyNum(1);                //快速幂部分        MyNum ans(1);        MyNum bottom(*this);        while (k) {                if (k & 1) {                        ans *= bottom;                }                bottom *= bottom;                k >>= 1;        }        ans.setPrecision();        return ans;}MyNum MyNum::power_decimal(const MyNum& decimal) const{        //ERROR        if ((*this).sign == -2) return *this;                if (decimal.sign == 0) return MyNum(1);        if (this->sign < 0)        //底数负数 不可进行小数幂                return ERROR.addError(2);        MyNum mult = this->My_log() * decimal;        //泰勒展开每一项要乘的东西        MyNum add(1);        MyNum ret;        for (int i = 1; add.sign != 0; i++) {                ret += add;                add = add * mult / MyNum(i);        }        return ret;}MyNum& MyNum::operator+=(const MyNum& other) {        *this = *this + other;        return *this;}MyNum& MyNum::operator-=(const MyNum& other) {        *this = *this - other;        return *this;}MyNum& MyNum::operator*=(const MyNum& other) {        *this = *this * other;        return *this;}MyNum& MyNum::operator/=(const MyNum& other) {        *this = *this / other;        return *this;}//显示MyNum MyNum::operator^(const MyNum& other) const{
  141.         //ERROR
  142.         if ((*this).sign == -2 || other.sign == -2) return *this + other;
  143.         MyNum b(other);
  144.         if (b.sign == 0) return (this->sign == 0) ? ERROR.addError(1) : ZERO;
  145.         if (this->sign == 0) return (b.sign > 0) ? ZERO : ERROR.addError(0);
  146.         //仅排除了底数为零的情况 不保证幂指数的整数部分和小数部分不为0
  147.         if (b.sign > 0)
  148.                 return power_int(other.to_int()) * (power_decimal(other.decimalpart()));        //整数部分快速幂 小数部分泰勒展开
  149.         else
  150.                 return MyNum(1) / (power_int(-other.to_int()) * (power_decimal(-other.decimalpart())));
  151. }
  152. MyNum MyNum::power_int(int k)const {                //整数部分
  153.         if (k == 0) return MyNum(1);
  154.         if (k < 0) return MyNum(1) / ((*this) ^ (-k));
  155.         if (*this == MyNum(1)) return MyNum(1);
  156.        
  157.         //快速幂部分
  158.         MyNum ans(1);
  159.         MyNum bottom(*this);
  160.         while (k) {
  161.                 if (k & 1) {
  162.                         ans *= bottom;
  163.                 }
  164.                 bottom *= bottom;
  165.                 k >>= 1;
  166.         }
  167.         ans.setPrecision();
  168.         return ans;
  169. }       
  170. MyNum MyNum::power_decimal(const MyNum& decimal) const{                //小数部分
  171.         //ERROR
  172.         if ((*this).sign == -2) return *this;
  173.        
  174.         if (decimal.sign == 0) return MyNum(1);
  175.         if (this->sign < 0)        //底数负数 不可进行小数幂
  176.                 return ERROR.addError(2);
  177.         MyNum mult = this->My_log() * decimal;        //泰勒展开每一项要乘的东西
  178.         MyNum add(1);
  179.         MyNum ret;
  180.         for (int i = 1; add.sign != 0; i++) {
  181.                 ret += add;
  182.                 add = add * mult / MyNum(i);
  183.         }
  184.         return ret;
  185. }void MyNum::setPrecision(int prec) {        int decimalpart = this->digits.size() - this->power;        //小数部分长度        if (decimalpart digits.empty())                        this->digits.pop_back();        int diff = 0;        //四舍五入的偏差值        if (!this->digits.empty()) {                if (this->digits.back() >= 5) {                        diff = 1;        //进1                }                this->digits.pop_back();        }        if (this->digits.empty()) {                *this = ZERO;        }        else {                int i = this->digits.size() - 1;                while (diff) {                        if (i == -1) break;                        this->digits[i] += diff;                        diff = this->digits[i] / 10;                        this->digits[i] %= 10;                        i--;                }                if (i == -1 && diff) {                        this->power++;                        this->digits.front() %= 10;                        this->digits.push_front(1);                }        }}
复制代码
Method.h
  1. #ifndef _METHOD_H_#define _METHOD_H_/*        Method类  存放计算式的原式 后缀表达式 以及 计算答案        string calstr                        //计算的原式        std::deque rpn        //ReversePolishNotation 逆波兰表示法/后缀表达式        int type                                //0 计算式  1 逻辑条件式        MyNum ans                                //计算结果*/#include #include #include #include "MyNum.h"using std::string;extern int SHOW_PRECISION;class Method{public:        //显示
  2.         void show() const;
  3.         void setPrecision(int prec = PRECISION);        void MyNum::show() const {
  4.         if (this->sign==-2) {
  5.                 printf("ERROR\n");
  6.                 for (int i = 0; i < digits.size(); i++) {
  7.                         if (digits[i])
  8.                                 std::cout << errorreason[i] << std::endl;
  9.                 }
  10.                 return;
  11.         }
  12.         if (sign == 2) {
  13.                 if (digits[0] == ',') return;
  14.                 for (int i = 0; i < digits.size(); i++)
  15.                         printf("%c", char(digits[i]));
  16.                 return;
  17.         }
  18.         int power = this->power;
  19.         int sign = this->sign;
  20.         std::deque<int> digits = this->digits;
  21.         if (sign == -1) printf("-");
  22.         if (sign == 0) { printf("0"); return; }
  23.         if (power <= 0) {
  24.                 printf("0.");
  25.                 while (power < 0) {
  26.                         printf("0"); power++;
  27.                 }
  28.                 power--;
  29.         }
  30.         for (int i = 0; i < digits.size(); i++) {
  31.                 if (power-- == 0) {
  32.                         printf(".");
  33.                 }
  34.                 printf("%d", digits[i]);
  35.         }
  36.         while (power > 0) {
  37.                 printf("0");
  38.                 power--;
  39.         }
  40. }        //显示        void showCalstr();        void showRPN();        void showAns(int showprecision=SHOW_PRECISION);        void show(int type = 0);private:        string calstr;        std::deque rpn;        int type;        MyNum ans;};#endif
复制代码
Method.cpp

[code]#include "Method.h"extern const MyNum ZERO;extern const MyNum ERROR;extern const MyNum ONE;//操作函数void Method::input(std::string str) {                //输入 将字符串中计算部分提取出来        for (int i = 0; i < str.size(); i++) {                if (str != ' ')                        calstr.push_back(str);        }}void Method::opstackpushback(std::deque& opstack,MyNum op) {        while (!opstack.empty() && opstack.back().power >= op.power) {                rpn.push_back(opstack.back());                opstack.pop_back();        }        opstack.push_back(op);}bool judgeop(char c) {                //判断是否为函数型op        if ((c < 'a' || c>'z') && (c < 'A' || c>'Z')) return false;        else return true;        return false;}void Method::changetorpn() {        this->rpn.clear();        std::deque& retrpn = this->rpn;        std::deque opstack;        //符号栈(用deque模拟栈)        string nowdigits;        string op;        for (int i = 0; i < calstr.size(); i++) {                if (calstr == ' ') continue;                if (calstr == ',') {                        if (!nowdigits.empty()) {                                retrpn.push_back(MyNum(nowdigits));                                nowdigits.clear();                        }                        while (!opstack.empty() && opstack.back() != MyNum("(")) {                                retrpn.push_back(opstack.back());                                opstack.pop_back();                        }                        //opstack.pop_back();                        continue;                }                if (calstr == '-' ) {                        if (!(!nowdigits.empty() || i > 0 && calstr[i - 1] == ')')) {        //'-'是负号不是减号                                if (!op.empty()) {                                        opstackpushback(opstack, MyNum(op));                                        op.clear();                                }                                opstackpushback(opstack, MyNum("neg"));                                continue;                        }                }                if (calstr >= '0' && calstr  b));                        }                        if (rpn == MyNum(">=")) {                                tempans.push_back(MyNum(a >= b));                        }                        if (rpn == MyNum("> ";        fflush(stdin);        scanf("%[^\n]", s);        string str(s);        if (str.empty()) {                getchar();                return -1;        }        if (str == "end")                 return 0;        if (str == "history") {                return 2;        }        if (str == "changeshowtype") {                showType = 1 - showType;                return 3;        }        if (str.size() > 12 && str.substr(0,12) == "setprecision") {                int newprecision = 0;                for (int i = 13; i < str.size(); i++) {                        newprecision *= 10;                        newprecision += str - '0';                }                SHOW_PRECISION = newprecision;                return 4;        }        Method m(str);        history.push_back(m);        return 1;}void Func() {        int input = 1;        while(true) {                input = inputMethod();                if (input == 0) break;                if (input == 1) {                        history.back().show(showType);                        cout "后输入计算式 回车即可显现结果  输入"end"回车即结束程序高级功能:        * 输入"changeshowtype"即可更改显示模式                - 简洁模式: 类似Matlab 回车只输出答案                - 详细模式: 输出原式, 后缀表达式 以及答案        * 输入"history"即可查看本次运行期间的计算记录        * 输入"setprecision 数字"即可更改显示答案精度 最高不超过20位)"




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4