免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234下一页
最近访问板块 发新帖
查看: 14742 | 回复: 30
打印 上一主题 下一主题

一个十进制大数运算类,支持加减乘除模、n次乘方、n次开方等运算 [复制链接]

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-08-18 13:08 |只看该作者 |倒序浏览
花了点时间写了这么个东西,目前只支持正整数的运算。
还有很多重要的功能,如素性的检测等还没有完成。
增加了负数 --20060823

decnum.h
  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <iostream>

  4. using namespace std;

  5. class decnum
  6. {
  7.     friend decnum pow(const decnum& x, int n);
  8.     friend decnum root(const decnum& x, int n);
  9.     friend decnum div(const decnum& x, const decnum& y, decnum& r);
  10.     friend decnum abs(const decnum& x);
  11.     friend bool operator==(const decnum& x, const decnum&y);
  12.     friend bool operator!=(const decnum& x, const decnum&y);
  13.     friend bool operator>(const decnum& x, const decnum&y);
  14.     friend bool operator<(const decnum& x, const decnum&y);
  15.     friend bool operator>=(const decnum& x, const decnum&y);
  16.     friend bool operator<=(const decnum& x, const decnum&y);
  17.     friend ostream& operator<<(ostream&os, const decnum& x);

  18. public:
  19.     decnum() : cap(0), num(0), sign(0), val(NULL) { }
  20.     decnum(const char *v, int n)
  21.     {
  22.         int i, j;
  23.         val = new char[n];
  24.         if(v[0] == '-') {
  25.             sign = 1;
  26.             v++;
  27.             n--;
  28.         }
  29.         else {
  30.             sign = 0;
  31.             if(v[0] == '+')
  32.                 v++;
  33.         }
  34.         for(i = 0; i < n && v[i] == '0'; i++);
  35.         for(j=0; i<n; i++, j++)
  36.             if(v[n-1-i] >= '0' && v[n-1-i] <= '9')
  37.                 val[j] = v[n-1-i] - '0';
  38.             else
  39.                 break;
  40.         num = j;
  41.         cap = n;
  42.     }
  43.     decnum(const decnum& x)
  44.     {
  45.         val = new char[x.num];
  46.         memcpy(val, x.val, x.num);
  47.         sign = x.sign;
  48.         num = x.num;
  49.         cap = x.num;
  50.     }
  51.     decnum(int x)
  52.     {
  53.         if(x==0) {
  54.             cap = num = 0;
  55.             val = NULL;
  56.             return;
  57.         }
  58.         if(x < 0) {
  59.             sign = 1;
  60.             x = -x;
  61.         }
  62.         else
  63.             sign = 0;
  64.         char temp[20];
  65.         sprintf(temp, "%d", x);
  66.         int n = strlen(temp);
  67.         num = cap = n;
  68.         val = new char[n];
  69.         for(int i=0; i<n; i++)
  70.             val[i] = temp[n-1-i] - '0';
  71.     }
  72.     decnum(long long x)
  73.     {
  74.         if(x==0) {
  75.             cap = num = 0;
  76.             val = NULL;
  77.             return;
  78.         }
  79.         if(x < 0) {
  80.             sign = 1;
  81.             x = -x;
  82.         }
  83.         else
  84.             sign = 0;
  85.         char temp[20];
  86.         sprintf(temp, "%lld", x);
  87.         int n = strlen(temp);
  88.         num = cap = n;
  89.         val = new char[n];
  90.         for(int i=0; i<n; i++)
  91.             val[i] = temp[n-1-i] - '0';
  92.     }
  93.     ~decnum() { delete[] val; }

  94.     int size() const { return num; }

  95.     decnum&
  96.     operator=(const decnum& x)
  97.     {
  98.         if (this != &x) {
  99.             if(cap < x.num) {
  100.                 delete[] val;
  101.                 val = new char[x.num];
  102.                 cap = x.num;
  103.             }
  104.             memcpy(val, x.val, x.num);
  105.             num = x.num;
  106.             sign = x.sign;
  107.         }
  108.         return *this;
  109.     }
  110.     decnum&
  111.     operator=(int x)
  112.     {
  113.         *this = decnum(x);
  114.         return *this;
  115.     }
  116.     decnum&
  117.     operator=(long long x)
  118.     {
  119.         *this = decnum(x);
  120.         return *this;
  121.     }

  122.     decnum& abs()
  123.     {
  124.         sign = 0;
  125.         return *this;
  126.     }
  127.     decnum& operator+=(const decnum& x);
  128.     decnum& operator-=(const decnum& x);
  129.     decnum& operator*=(const decnum& x);
  130.     decnum& operator/=(const decnum& x);
  131.     decnum& operator%=(const decnum& x);
  132.     decnum  operator+(const decnum& x) const;
  133.     decnum  operator-(const decnum& x) const;
  134.     decnum  operator*(const decnum& x) const;
  135.     decnum  operator/(const decnum& x) const;
  136.     decnum  operator%(const decnum& x) const;

  137.     bool ispow(int n, decnum& r) const;
  138.     bool ispow() const;
  139. private:
  140.     int  cap;
  141.     int  num;
  142.     int  sign;
  143.     char *val;
  144. private:
  145.     char root_1(int n);
  146.     decnum& absadd(const decnum& x);
  147.     decnum& abssub(const decnum& x);
  148.     bool absge(const decnum& x);
  149. };

复制代码


decnum.cpp

  1. #include "decnum.h"

  2. decnum&
  3. decnum::absadd(const decnum& x)
  4. {
  5.     int i, max;
  6.     char carry = 0, ch;

  7.     if(x.num == 0) return *this;
  8.     if(num < x.num)
  9.         max = x.num + 1;
  10.     else
  11.         max = num + 1;
  12.     if(max > cap)
  13.     {
  14.         cap = max;
  15.         char *newval = new char[cap];
  16.         memcpy(newval, val, num);
  17.         memset(newval+num, 0, cap - num);
  18.         delete[] val;
  19.         val = newval;
  20.     }
  21.     else
  22.     {
  23.         memset(val+num, 0, max - num);
  24.     }
  25.     num = max-1;
  26.     for(i=0; i<x.num; i++) {
  27.         ch = val[i] + x.val[i] + carry;
  28.         if(ch > 9) {
  29.             carry = 1;
  30.             val[i] = ch - 10;
  31.         }
  32.         else {
  33.             carry = 0;
  34.             val[i] = ch;
  35.         }
  36.     }
  37.     for(; i<=num && carry == 1; i++) {
  38.         ch = val[i] + 1;
  39.         if(ch > 9) {
  40.             carry = 1;
  41.             val[i] = ch - 10;
  42.         }
  43.         else {
  44.             carry = 0;
  45.             val[i] = ch;
  46.         }
  47.     }
  48.     if(i>num) num = i;
  49.     return *this;
  50. }

  51. decnum&
  52. decnum::abssub(const decnum& x)
  53. {
  54.     if(x.num == 0) return *this;
  55.     int i;
  56.     char carry = 0, ch;
  57.     for(i=0; i<x.num; i++) {
  58.         ch = val[i] - x.val[i] - carry;
  59.         if(ch < 0) {
  60.             carry = 1;
  61.             val[i] = ch + 10;
  62.         }
  63.         else {
  64.             carry = 0;
  65.             val[i] = ch;
  66.         }
  67.     }
  68.     for(; i<num && carry == 1; i++) {
  69.         ch = val[i] - 1;
  70.         if(ch < 0) {
  71.             carry = 1;
  72.             val[i] = ch + 10;
  73.         }
  74.         else {
  75.             carry = 0;
  76.             val[i] = ch;
  77.         }
  78.     }
  79.     for(i=num; i>0 && val[i-1] == 0; i--);
  80.     num = i;
  81.     return *this;
  82. }

  83. bool
  84. decnum::absge(const decnum& x)
  85. {
  86.     if(num > x.num) return true;
  87.     if(num < x.num) return false;
  88.     for(int i=num-1; i >= 0; i--)
  89.         if(val[i] > x.val[i])
  90.             return true;
  91.         else if(val[i] < x.val[i])
  92.             return false;
  93.     return true;
  94. }

  95. decnum&
  96. decnum::operator+=(const decnum& x)
  97. {
  98.     if(x.sign == sign)
  99.         return absadd(x);
  100.     else if(absge(x))
  101.         return abssub(x);
  102.     else {
  103.         decnum tmp(*this);
  104.         *this = x;
  105.         return abssub(tmp);
  106.     }
  107. }

  108. decnum&
  109. decnum::operator-=(const decnum& x)
  110. {
  111.     if(x.sign != sign)
  112.         return absadd(x);
  113.     else if(absge(x))
  114.         return abssub(x);
  115.     else {
  116.         decnum tmp(*this);
  117.         *this = x;
  118.         return abssub(tmp);
  119.     }
  120. }

  121. decnum&
  122. decnum::operator*=(const decnum& x)
  123. {
  124.     if(num == 0) return *this;
  125.     if(x.num == 0) {
  126.         num = 0;
  127.         return *this;
  128.     }
  129.     if(sign == x.sign)
  130.         sign = 0;
  131.     else
  132.         sign = 1;
  133.     int mul, i, n, newcap, max;
  134.     char ch, carry;
  135.     char *newval = new char[num + x.num];
  136.     newcap = num + x.num;
  137.     memset(newval, 0, num + x.num);

  138.     decnum a, b;
  139.     char *ptr;
  140.     for(i=0; i<num && val[i] == 0; i++);
  141.     int na = i;
  142.     a.val = val + i;
  143.     a.num = num - i;
  144.     for(i=0; i<num && x.val[i] == 0; i++);
  145.     int nb = i;
  146.     b.val = x.val + i;
  147.     b.num = x.num - i;
  148.     ptr = newval + na + nb;

  149.     for(n=0; n <= a.num + b.num - 2; n++) {
  150.         mul = 0;
  151.         if(n > b.num - 1)
  152.             i = n - b.num + 1;
  153.         else
  154.             i=0;
  155.         max = n < a.num-1 ? n : a.num-1;
  156.         for(; i<=max; i++)
  157.             mul += a.val[i]*b.val[n-i];
  158.         carry = 0;
  159.         for(i=n; mul > 0 || carry > 0; mul /= 10, i++) {
  160.             ch = ptr[i] + mul % 10 + carry;
  161.             if(ch > 9) {
  162.                 carry = 1;
  163.                 ptr[i] = ch - 10;
  164.             }
  165.             else
  166.             {
  167.                 carry = 0;
  168.                 ptr[i] = ch;
  169.             }
  170.         }
  171.     }
  172.     for(i=a.num + b.num; i>0 && ptr[i-1] == 0; i--);
  173.     num = i + na + nb;
  174.     if(cap >= num) {
  175.         memcpy(val, newval, num);
  176.         delete[] newval;
  177.     }
  178.     else {
  179.         cap = newcap;
  180.         delete[] val;
  181.         val = newval;
  182.     }
  183.     a.val = b.val = NULL;
  184.     return *this;
  185. }

  186. decnum&
  187. decnum::operator/=(const decnum& x)
  188. {
  189.     char ch, carry, fac;
  190.     decnum tmp;
  191.     int i;
  192.     if(x.num == 0) return *this;
  193.     if(num < x.num) {
  194.         num = 0;
  195.         return *this;
  196.     }
  197.     if(sign == x.sign)
  198.         sign = 0;
  199.     else
  200.         sign = 1;
  201.     char *newval = new char[num - x.num + 1];
  202.     memset(newval, 0, num - x.num + 1);
  203.     carry = 0;
  204.     fac = x.val[x.num-1] + 1;
  205.     tmp.val = val + num - x.num + 1;
  206.     tmp.cap = tmp.num = x.num -1;
  207.     for(i=num-1; i>= x.num-1; i--) {
  208.         tmp.val--;
  209.         tmp.num++;
  210.         ch = (carry * 10 + val[i]) / fac;
  211.         tmp  -= x * ch;
  212.         while(tmp >= x) {
  213.             tmp -= x;
  214.             ch++;
  215.         }
  216.         newval[i-x.num+1] = ch;
  217.         carry = val[i];
  218.     }
  219.     tmp.val = NULL;
  220.     for(i=num-x.num+1; i>0 && newval[i-1] == 0; i--);
  221.     num = i;
  222.     delete[] val;
  223.     val = newval;
  224.     return *this;
  225. }

  226. decnum&
  227. decnum::operator%=(const decnum& x)
  228. {
  229.     char ch, carry, fac;
  230.     decnum tmp;
  231.     int i;
  232.     if(x.num == 0) return *this;
  233.     if(num < x.num) return *this;

  234.     carry = 0;
  235.     fac = x.val[x.num-1] + 1;
  236.     tmp.val = val + num - x.num + 1;
  237.     tmp.num = x.num - 1;
  238.     for(i=num-1; i>= x.num-1; i--) {
  239.         tmp.val--;
  240.         tmp.num++;
  241.         ch = (carry * 10 + val[i]) / fac;
  242.         tmp  -= x * ch;
  243.         while(tmp >= x) {
  244.             tmp -= x;
  245.             ch++;
  246.         }
  247.         carry = val[i];
  248.     }
  249.     tmp.val = NULL;
  250.     num = tmp.num;
  251.     return *this;
  252. }

  253. decnum
  254. decnum::operator+(const decnum& x) const
  255. {
  256.     decnum tmp = *this;
  257.     return tmp += x;
  258. }

  259. decnum
  260. decnum::operator-(const decnum& x) const
  261. {
  262.     decnum tmp = *this;
  263.     return tmp -= x;
  264. }

  265. decnum
  266. decnum::operator*(const decnum& x) const
  267. {
  268.     decnum tmp = *this;
  269.     return tmp *= x;
  270. }

  271. decnum
  272. decnum::operator/(const decnum& x) const
  273. {
  274.     decnum tmp = *this;
  275.     return tmp /= x;
  276. }

  277. decnum
  278. decnum::operator%(const decnum& x) const
  279. {
  280.     decnum tmp = *this;
  281.     return tmp %= x;
  282. }

  283. decnum abs(const decnum& x)
  284. {
  285.     decnum tmp(x);
  286.     tmp.sign = 0;
  287.     return tmp;
  288. }

  289. decnum pow(const decnum& x, int n)
  290. {
  291.     decnum tmp(1), fac(x);
  292.     for(; n>0; n>>=1) {
  293.         if(n&0x01)
  294.             tmp *= fac;
  295.         fac *= fac;
  296.     }
  297.     return tmp;
  298. }

  299. char decnum::root_1(int n)
  300. {
  301.     char r = (int)(pow(1+val[num-1], 1.0/n) * pow(10,(num-1.0)/n));
  302.     for(; r>0 && pow(decnum(r), n) > *this; r--);
  303.     return r;
  304. }

  305. bool decnum::ispow(int n, decnum& r) const
  306. {
  307.     if(num == 0) {
  308.         r.num = 0;
  309.         return true;
  310.     }
  311.     if(sign == 1 && (n&1 == 0)) {
  312.         r.num = 0;
  313.         return false;
  314.     }
  315.     decnum tmp, p;
  316.     r.cap = r.num = (num+n-1) / n;
  317.     r.val = new char[r.num];
  318.     r.sign = sign;
  319.     memset(r.val, 0, r.num);
  320.     tmp.val = val + (r.num-1)*n;
  321.     tmp.num = num - (r.num-1)*n;
  322.     r.val[r.num-1] = tmp.root_1(n);

  323.     tmp.val = new char[r.num+1];
  324.     tmp.cap = r.num+1;
  325.     int v;
  326.     p = pow(r, n);
  327.     if(p == *this) return true;
  328.     for(int i=r.num-2; i>=0; i--) {
  329.         memset(tmp.val, 0, i+1);
  330.         tmp.val[i] = 1;
  331.         tmp.num = i+1;
  332.         tmp += r;
  333.         p = (*this - p) / (pow(tmp, n) - p);
  334.         if(p.num > 1)
  335.             v = 9;
  336.         else if(p.num > 0)
  337.             v = p.val[0];
  338.         else
  339.             v = 0;
  340.         for(; v>=0; v--) {
  341.             r.val[i] = v;
  342.             p = pow(r, n);
  343.             if(p == *this)
  344.                 return true;
  345.             if(p < *this)
  346.                 break;
  347.         }
  348.     }
  349.     return false;
  350. }

  351. bool decnum::ispow() const
  352. {
  353.     decnum r, dec2("2", 1);
  354.     if(ispow(2, r)) return true;
  355.     for(int n=3; r > dec2; n+=2) {
  356.         if(ispow(n, r)) return true;
  357.     }
  358.     return false;
  359. }

  360. decnum
  361. root(const decnum& x, int n)
  362. {
  363.     decnum r;
  364.     x.ispow(n, r);
  365.     return r;
  366. }

  367. decnum
  368. div(const decnum& x, const decnum& y, decnum& r)
  369. {
  370.     char ch, carry, fac;
  371.     decnum d = x, tmp;
  372.     int i;
  373.     if(y.num == 0) return x;
  374.     if(d.num < y.num) {
  375.         r = x;
  376.         d = 0;
  377.         return d;
  378.     }
  379.     char *newval = new char[d.num - y.num + 1];
  380.     memset(newval, 0, d.num - y.num + 1);
  381.     carry = 0;
  382.     fac = y.val[y.num-1] + 1;
  383.     tmp.val = d.val + d.num - y.num + 1;
  384.     tmp.num = y.num - 1;
  385.     for(i=d.num-1; i>= y.num-1; i--) {
  386.         tmp.val--;
  387.         tmp.num++;
  388.         ch = (carry * 10 + d.val[i]) / fac;
  389.         tmp  -= y * ch;
  390.         while(tmp >= y) {
  391.             tmp -= y;
  392.             ch++;
  393.         }
  394.         newval[i-y.num+1] = ch;
  395.         carry = d.val[i];
  396.     }
  397.     r = tmp;
  398.     tmp.val = NULL;
  399.     for(i=d.num-y.num+1; i>0 && newval[i-1] == 0; i--);
  400.     d.num = i;
  401.     delete[] d.val;
  402.     d.val = newval;
  403.     return d;
  404. }

  405. bool operator==(const decnum& x, const decnum&y)
  406. {
  407.     if(x.sign != y.sign) return false;
  408.     if(x.num != y.num) return false;
  409.     for(int i=0; i < x.num; i++)
  410.         if(x.val[i] != y.val[i])
  411.             return false;
  412.     return true;
  413. }

  414. bool operator!=(const decnum& x, const decnum&y)
  415. {
  416.     return !(x==y);
  417. }

  418. bool operator>(const decnum& x, const decnum&y)
  419. {
  420.     if(x.sign > y.sign) return false;
  421.     if(x.sign < y.sign) return true;
  422.     bool retval = (x.sign == 0);
  423.     if(x.num > y.num) return retval;
  424.     if(x.num < y.num) return !retval;
  425.     for(int i=x.num-1; i >= 0; i--)
  426.         if(x.val[i] > y.val[i])
  427.             return retval;
  428.         else if(x.val[i] < y.val[i])
  429.             return !retval;
  430.     return false;
  431. }

  432. bool operator<(const decnum& x, const decnum&y)
  433. {
  434.     return y > x;
  435. }

  436. bool operator>=(const decnum& x, const decnum&y)
  437. {
  438.     if(x.sign > y.sign) return false;
  439.     if(x.sign < y.sign) return true;
  440.     bool retval = (x.sign == 0);
  441.     if(x.num > y.num) return retval;
  442.     if(x.num < y.num) return !retval;
  443.     for(int i=x.num-1; i >= 0; i--)
  444.         if(x.val[i] > y.val[i])
  445.             return retval;
  446.         else if(x.val[i] < y.val[i])
  447.             return !retval;
  448.     return true;
  449. }

  450. bool operator<=(const decnum& x, const decnum&y)
  451. {
  452.     return y >= x;
  453. }

  454. ostream& operator<<(ostream&os, const decnum& x)
  455. {
  456.     if(x.size() == 0)
  457.         os << 0;
  458.     else {
  459.         if(x.sign == 1)
  460.             os << "-";
  461.         for(int i = x.size()-1; i>=0; i--)
  462.             os << (int)x.val[i];
  463.     }
  464.     return os;
  465. }

复制代码

[ 本帖最后由 yuxh 于 2006-8-23 18:11 编辑 ]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
2 [报告]
发表于 2006-08-18 13:16 |只看该作者
传说中的沙发?

论坛徽章:
0
3 [报告]
发表于 2006-08-18 13:18 |只看该作者
8错, 对我搞科学计算有用, 测试过效率么?

论坛徽章:
0
4 [报告]
发表于 2006-08-18 13:21 |只看该作者
最好再加上超高精度的浮点数的混合运算支持

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
5 [报告]
发表于 2006-08-18 13:26 |只看该作者
这个本来是为大素数的测试用的,这些是要用到的基本运算
可惜我的工作与加密算法无关,纯粹是业余爱好,代码也是业余水平的。
就效率而言,比较慢的就是求n次方根这个了:
root(x, n)
设x有m位,则算法应该是O(m^3*log(m)/n)的
检测一个数是否是某个数的整数次幂:
ispow()
这个就差不多是O(m^3*log(m)^2)的了

[ 本帖最后由 yuxh 于 2006-8-22 11:17 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2006-08-18 15:00 |只看该作者
支持原创
顶一下吧

论坛徽章:
0
7 [报告]
发表于 2006-08-19 15:25 |只看该作者
come on

论坛徽章:
2
技术图书徽章
日期:2013-09-04 15:21:51酉鸡
日期:2013-11-01 21:20:20
8 [报告]
发表于 2006-08-21 15:02 |只看该作者
接口为10进制, 内部的进制采用unsigned long或unsigned short,是不是更能借助逻辑运算,提高效率?

论坛徽章:
0
9 [报告]
发表于 2006-08-22 10:29 |只看该作者

回复 1楼 yuxh 的帖子

来凑凑热闹
decimal.h
/***************************************************************************
                          decimal.h  -  description
                             -------------------
    begin                : Wed Jan 9 2002
    copyright            : (C) 2002 by Xian Yining
    email                : hqxyn@yahoo.com.cn
***************************************************************************/

/***************************************************************************
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
***************************************************************************/
#ifndef DECIMAL_H
#define DECIMAL_H

#ifndef __USE_GNU
#define __USE_GNU
#endif
/*
#ifndef __USE_ISOC99
#define __USE_ISOC99
#endif
*/
#include <typeinfo>
#include <iostream>
#include <string>
#include <limits>

const unsigned DECIMAL_DEFAULT_PRE = 20,DECIMAL_DEFAULT_DEC = 6;

class decimal
{
public :
        enum Sign {PLUS=1,MINUS=-1};
        enum Stat {NOINIT=-1,OK,UPFLOW,DOWNFLOW,OVERDIGITS};
        enum Pre  {DOUBLE_PRECISION=std::numeric_limits<double>::digits10,LDOUBLE_PRECISION=std::numeric_limits<long double>::digits10};

        //构造函数
        decimal(void):sn(PLUS),val("0",exp(0),st(OK),pre(DECIMAL_DEFAULT_PRE),dec(DECIMAL_DEFAULT_DEC) {}
        decimal(const std::string &,const unsigned int p=DECIMAL_DEFAULT_PRE,const unsigned int d=DECIMAL_DEFAULT_DEC) ;
        decimal(const char* cstr,const unsigned int p=DECIMAL_DEFAULT_PRE,const unsigned int d=DECIMAL_DEFAULT_DEC) ;
        decimal(const int,const unsigned int p=DECIMAL_DEFAULT_PRE,const unsigned int d=DECIMAL_DEFAULT_DEC) ;
        decimal(const unsigned int,const unsigned int p=DECIMAL_DEFAULT_PRE,const unsigned int d=DECIMAL_DEFAULT_DEC) ;
        decimal(const long,const unsigned int p=DECIMAL_DEFAULT_PRE,const unsigned int d=DECIMAL_DEFAULT_DEC) ;
        decimal(const long long,const unsigned int p=DECIMAL_DEFAULT_PRE,const unsigned int d=DECIMAL_DEFAULT_DEC) ;
        decimal(const unsigned long,const unsigned int p=DECIMAL_DEFAULT_PRE,const unsigned int d=DECIMAL_DEFAULT_DEC) ;
        decimal(const unsigned long long,const unsigned int p=DECIMAL_DEFAULT_PRE,const unsigned int d=DECIMAL_DEFAULT_DEC) ;
        decimal(const double,const unsigned int p=DECIMAL_DEFAULT_PRE,const unsigned int d=DECIMAL_DEFAULT_DEC) ;
        decimal(const long double,const unsigned int p=DECIMAL_DEFAULT_PRE,const unsigned int d=DECIMAL_DEFAULT_DEC) ;
        decimal(const decimal& d):sn(d.sn),val(d.val),exp(d.exp),st(d.st),pre(d.pre),dec(d.dec) {}
        virtual ~decimal(){}
        //赋值
        decimal& operator=(const decimal& ;
        //算术运算
        decimal& operator +=(const decimal& ;
        decimal& operator -=(const decimal& ;
        decimal& operator *=(const decimal& ;
        decimal& operator /=(const decimal& ;
//        decimal& operator %=(const decimal& ;

        //比较运算符
        bool le(const decimal& const ;
        bool eq(const decimal& const ;
        bool gt(const decimal& const ;
       
        decimal& operator-(void) {sn=((sn==PLUS)?MINUSLUS);return *this;}
        decimal& operator+(void) {return *this;}
        //杂项函数
        virtual std::string toString() const;
        virtual std::string toShortStr() const;
        virtual std::string toString(const unsigned int len,const int de) const;
                                                                //在len长度内转为十进小数字符串,超常则返回‘*’串
        virtual std::string toEString(const unsigned int len=0) const;        //在len长度内转为科学表示法字符串,超常则返回‘*’串
        bool ok() const {return (st==OK)?true:false;}                //数字是否有效
        bool zero() const {return (val=="0")?true:false ;}        //数字是否为0
        virtual decimal& round(int r) ;
        virtual decimal& round() ;        //按dec指定的位数四舍五入
       
        Sign getSn() const {return sn;}
        const std::string &getVal() const {return val;}
        int getExp() const {return exp;}
        Stat getSt() const {return st;}
        unsigned getPre() const {return pre;}
        unsigned getDec() const {return dec;}
/****************
*   内部子程序   *
****************/
protected :
        decimal& decReg() ;
       
        decimal& decAdd(const decimal&);
        decimal& decSub(const decimal&);
        decimal& decMulti(const decimal&) ;
        decimal& decDiv(const decimal&);

        void valDiv(std::string& s1,const std::string& s2,const unsigned len) ;
        char valMult(std::string& s1,const std::string& s2) ;
        void valAdd(std::string& s1,int &p1,const std::string& s2,int p2) ;
        int valSub(std::string& s1,int &e1,const std::string& s2,const int e2);
       
        int digitAdd(char& c1,const char c2,const int car=0) ;
        int digitSub(char& c1,const char c2,const int b=0) ;
        char digitMult(char& c1,const char c2,const char m) ;
       
        int valCmp(const std::string& s1,const int e1,const std::string& s2,const int e2) const;
       
        void setSn(Sign s) {sn=s;}
        void setVal(const std::string &s) {val=s;}
        void setExp(int i) {exp=i;}
        void setSt(Stat s) {st=s;}
        void setPre(unsigned u) {pre=u;}
        void setDec(unsigned u) {dec=u;}
private :
        Sign                sn;        //符号
        std::string        val;        //有效尾数
        int                 exp;        //小数点位置(指数)
        //以下为辅助参数
        Stat                st;        //状态
        unsigned int        pre;        //精度(最大有效数字位数)
        unsigned int        dec;        //保留小数位数
       
};

/*******************
*   协作函数       *
*******************/
decimal round(const decimal& ,const int) ;
//算术运算
decimal operator +(const decimal&,const decimal&) ;
decimal operator -(const decimal&,const decimal&) ;
decimal operator *(const decimal&,const decimal&) ;
decimal operator /(const decimal&,const decimal&) ;
//        friend decimal& operator %(const decimal&,const decimal&) ;
//比较运算符
bool operator  <(const decimal&,const decimal&) ;
bool operator <=(const decimal&,const decimal&) ;
bool operator ==(const decimal&,const decimal&) ;
bool operator >=(const decimal&,const decimal&) ;
bool operator  >(const decimal&,const decimal&) ;
bool operator !=(const decimal&,const decimal&) ;
//流
std:stream& operator <<(std:stream&,const decimal&) ;
//unsigned int midDigits(const decimal& ,const decimal& ) ;

#endif //DECIMAL_H

[ 本帖最后由 hqxyn 于 2006-8-22 19:54 编辑 ]

论坛徽章:
0
10 [报告]
发表于 2006-08-22 10:31 |只看该作者

回复 9楼 hqxyn 的帖子

money.h
/***************************************************************************
                          decimal.cpp  -  description
                             -------------------
    begin                : Wed Jan 9 2002
    copyright            : (C) 2002 by Xian Yining
    email                : hqxyn@yahoo.com.cn
***************************************************************************/

/***************************************************************************
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
***************************************************************************/
#ifndef _MONEY_H
#define _MONEY_H

#include "decimal.h"

const int MONEY_DEFAULT_DEC = 2;

class money : public decimal {
public :
money():decimal(0,DECIMAL_DEFAULT_PRE,MONEY_DEFAULT_DEC) {};
money(const char* cstr,const unsigned int p=DECIMAL_DEFAULT_PRE)
                :decimal(cstr,p,MONEY_DEFAULT_DEC) {round();} ;
money(const int i,const unsigned int p=DECIMAL_DEFAULT_PRE)
                :decimal(i,p,MONEY_DEFAULT_DEC){round();} ;
money(const unsigned int ui,const unsigned int p=DECIMAL_DEFAULT_PRE)
                :decimal(ui,p,MONEY_DEFAULT_DEC){round();} ;
money(const long l,const unsigned int p=DECIMAL_DEFAULT_PRE)
                :decimal(l,p,MONEY_DEFAULT_DEC){round();} ;
money(const long long ll,const unsigned int p=DECIMAL_DEFAULT_PRE)
                :decimal(ll,p,MONEY_DEFAULT_DEC){round();} ;
money(const unsigned long ul,const unsigned int p=DECIMAL_DEFAULT_PRE)
                :decimal(ul,p,MONEY_DEFAULT_DEC){round();} ;
money(const unsigned long long ull,const unsigned int p=DECIMAL_DEFAULT_PRE)
                :decimal(ull,p,MONEY_DEFAULT_DEC){round();} ;
money(const double db,const unsigned int p=DECIMAL_DEFAULT_PRE)
                :decimal(db,p,MONEY_DEFAULT_DEC){round();} ;
money(const long double ld,const unsigned int p=DECIMAL_DEFAULT_PRE)
                :decimal(ld,p,MONEY_DEFAULT_DEC){round();} ;
money(const decimal& d)
                :decimal(0,d.getPre(),MONEY_DEFAULT_DEC) {
                setSn(d.getSn());
                setVal(d.getVal());
                setExp(d.getExp());
                round();}
//赋值d.toEString().c_str()

money& operator=(const decimal& d) {
        //精度定义(pre)和保留小数位数(dec)在变量定义时确定,?新值时不变。
        setSn(d.getSn());
        setVal(d.getVal());
        setExp(d.getExp());
        if (getVal().size()>getPre()) {setSt(OVERDIGITS);}
        else setSt(d.getSt());
        round();
        return *this;
}
};
#endif //_MONEY_H

[ 本帖最后由 hqxyn 于 2006-8-22 10:38 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP