花了点时间写了这么个东西,目前只支持正整数的运算。
还有很多重要的功能,如素性的检测等还没有完成。
增加了负数 --20060823
decnum.h
#include <stdio.h>
#include <math.h>
#include <iostream>
using namespace std;
class decnum
{
friend decnum pow(const decnum& x, int n);
friend decnum root(const decnum& x, int n);
friend decnum div(const decnum& x, const decnum& y, decnum& r);
friend decnum abs(const decnum& x);
friend bool operator==(const decnum& x, const decnum&y);
friend bool operator!=(const decnum& x, const decnum&y);
friend bool operator>(const decnum& x, const decnum&y);
friend bool operator<(const decnum& x, const decnum&y);
friend bool operator>=(const decnum& x, const decnum&y);
friend bool operator<=(const decnum& x, const decnum&y);
friend ostream& operator<<(ostream&os, const decnum& x);
public:
decnum() : cap(0), num(0), sign(0), val(NULL) { }
decnum(const char *v, int n)
{
int i, j;
val = new char[n];
if(v[0] == '-') {
sign = 1;
v++;
n--;
}
else {
sign = 0;
if(v[0] == '+')
v++;
}
for(i = 0; i < n && v == '0'; i++);
for(j=0; i<n; i++, j++)
if(v[n-1-i] >= '0' && v[n-1-i] <= '9')
val[j] = v[n-1-i] - '0';
else
break;
num = j;
cap = n;
}
decnum(const decnum& x)
{
val = new char[x.num];
memcpy(val, x.val, x.num);
sign = x.sign;
num = x.num;
cap = x.num;
}
decnum(int x)
{
if(x==0) {
cap = num = 0;
val = NULL;
return;
}
if(x < 0) {
sign = 1;
x = -x;
}
else
sign = 0;
char temp[20];
sprintf(temp, "%d", x);
int n = strlen(temp);
num = cap = n;
val = new char[n];
for(int i=0; i<n; i++)
val = temp[n-1-i] - '0';
}
decnum(long long x)
{
if(x==0) {
cap = num = 0;
val = NULL;
return;
}
if(x < 0) {
sign = 1;
x = -x;
}
else
sign = 0;
char temp[20];
sprintf(temp, "%lld", x);
int n = strlen(temp);
num = cap = n;
val = new char[n];
for(int i=0; i<n; i++)
val = temp[n-1-i] - '0';
}
~decnum() { delete[] val; }
int size() const { return num; }
decnum&
operator=(const decnum& x)
{
if (this != &x) {
if(cap < x.num) {
delete[] val;
val = new char[x.num];
cap = x.num;
}
memcpy(val, x.val, x.num);
num = x.num;
sign = x.sign;
}
return *this;
}
decnum&
operator=(int x)
{
*this = decnum(x);
return *this;
}
decnum&
operator=(long long x)
{
*this = decnum(x);
return *this;
}
decnum& abs()
{
sign = 0;
return *this;
}
decnum& operator+=(const decnum& x);
decnum& operator-=(const decnum& x);
decnum& operator*=(const decnum& x);
decnum& operator/=(const decnum& x);
decnum& operator%=(const decnum& x);
decnum operator+(const decnum& x) const;
decnum operator-(const decnum& x) const;
decnum operator*(const decnum& x) const;
decnum operator/(const decnum& x) const;
decnum operator%(const decnum& x) const;
bool ispow(int n, decnum& r) const;
bool ispow() const;
private:
int cap;
int num;
int sign;
char *val;
private:
char root_1(int n);
decnum& absadd(const decnum& x);
decnum& abssub(const decnum& x);
bool absge(const decnum& x);
};
decnum.cpp
#include "decnum.h"
decnum&
decnum::absadd(const decnum& x)
{
int i, max;
char carry = 0, ch;
if(x.num == 0) return *this;
if(num < x.num)
max = x.num + 1;
else
max = num + 1;
if(max > cap)
{
cap = max;
char *newval = new char[cap];
memcpy(newval, val, num);
memset(newval+num, 0, cap - num);
delete[] val;
val = newval;
}
else
{
memset(val+num, 0, max - num);
}
num = max-1;
for(i=0; i<x.num; i++) {
ch = val + x.val + carry;
if(ch > 9) {
carry = 1;
val = ch - 10;
}
else {
carry = 0;
val = ch;
}
}
for(; i<=num && carry == 1; i++) {
ch = val + 1;
if(ch > 9) {
carry = 1;
val = ch - 10;
}
else {
carry = 0;
val = ch;
}
}
if(i>num) num = i;
return *this;
}
decnum&
decnum::abssub(const decnum& x)
{
if(x.num == 0) return *this;
int i;
char carry = 0, ch;
for(i=0; i<x.num; i++) {
ch = val - x.val - carry;
if(ch < 0) {
carry = 1;
val = ch + 10;
}
else {
carry = 0;
val = ch;
}
}
for(; i<num && carry == 1; i++) {
ch = val - 1;
if(ch < 0) {
carry = 1;
val = ch + 10;
}
else {
carry = 0;
val = ch;
}
}
for(i=num; i>0 && val[i-1] == 0; i--);
num = i;
return *this;
}
bool
decnum::absge(const decnum& x)
{
if(num > x.num) return true;
if(num < x.num) return false;
for(int i=num-1; i >= 0; i--)
if(val > x.val)
return true;
else if(val < x.val)
return false;
return true;
}
decnum&
decnum::operator+=(const decnum& x)
{
if(x.sign == sign)
return absadd(x);
else if(absge(x))
return abssub(x);
else {
decnum tmp(*this);
*this = x;
return abssub(tmp);
}
}
decnum&
decnum::operator-=(const decnum& x)
{
if(x.sign != sign)
return absadd(x);
else if(absge(x))
return abssub(x);
else {
decnum tmp(*this);
*this = x;
return abssub(tmp);
}
}
decnum&
decnum::operator*=(const decnum& x)
{
if(num == 0) return *this;
if(x.num == 0) {
num = 0;
return *this;
}
if(sign == x.sign)
sign = 0;
else
sign = 1;
int mul, i, n, newcap, max;
char ch, carry;
char *newval = new char[num + x.num];
newcap = num + x.num;
memset(newval, 0, num + x.num);
decnum a, b;
char *ptr;
for(i=0; i<num && val == 0; i++);
int na = i;
a.val = val + i;
a.num = num - i;
for(i=0; i<num && x.val == 0; i++);
int nb = i;
b.val = x.val + i;
b.num = x.num - i;
ptr = newval + na + nb;
for(n=0; n <= a.num + b.num - 2; n++) {
mul = 0;
if(n > b.num - 1)
i = n - b.num + 1;
else
i=0;
max = n < a.num-1 ? n : a.num-1;
for(; i<=max; i++)
mul += a.val*b.val[n-i];
carry = 0;
for(i=n; mul > 0 || carry > 0; mul /= 10, i++) {
ch = ptr + mul % 10 + carry;
if(ch > 9) {
carry = 1;
ptr = ch - 10;
}
else
{
carry = 0;
ptr = ch;
}
}
}
for(i=a.num + b.num; i>0 && ptr[i-1] == 0; i--);
num = i + na + nb;
if(cap >= num) {
memcpy(val, newval, num);
delete[] newval;
}
else {
cap = newcap;
delete[] val;
val = newval;
}
a.val = b.val = NULL;
return *this;
}
decnum&
decnum::operator/=(const decnum& x)
{
char ch, carry, fac;
decnum tmp;
int i;
if(x.num == 0) return *this;
if(num < x.num) {
num = 0;
return *this;
}
if(sign == x.sign)
sign = 0;
else
sign = 1;
char *newval = new char[num - x.num + 1];
memset(newval, 0, num - x.num + 1);
carry = 0;
fac = x.val[x.num-1] + 1;
tmp.val = val + num - x.num + 1;
tmp.cap = tmp.num = x.num -1;
for(i=num-1; i>= x.num-1; i--) {
tmp.val--;
tmp.num++;
ch = (carry * 10 + val) / fac;
tmp -= x * ch;
while(tmp >= x) {
tmp -= x;
ch++;
}
newval[i-x.num+1] = ch;
carry = val;
}
tmp.val = NULL;
for(i=num-x.num+1; i>0 && newval[i-1] == 0; i--);
num = i;
delete[] val;
val = newval;
return *this;
}
decnum&
decnum::operator%=(const decnum& x)
{
char ch, carry, fac;
decnum tmp;
int i;
if(x.num == 0) return *this;
if(num < x.num) return *this;
carry = 0;
fac = x.val[x.num-1] + 1;
tmp.val = val + num - x.num + 1;
tmp.num = x.num - 1;
for(i=num-1; i>= x.num-1; i--) {
tmp.val--;
tmp.num++;
ch = (carry * 10 + val) / fac;
tmp -= x * ch;
while(tmp >= x) {
tmp -= x;
ch++;
}
carry = val;
}
tmp.val = NULL;
num = tmp.num;
return *this;
}
decnum
decnum::operator+(const decnum& x) const
{
decnum tmp = *this;
return tmp += x;
}
decnum
decnum::operator-(const decnum& x) const
{
decnum tmp = *this;
return tmp -= x;
}
decnum
decnum::operator*(const decnum& x) const
{
decnum tmp = *this;
return tmp *= x;
}
decnum
decnum::operator/(const decnum& x) const
{
decnum tmp = *this;
return tmp /= x;
}
decnum
decnum::operator%(const decnum& x) const
{
decnum tmp = *this;
return tmp %= x;
}
decnum abs(const decnum& x)
{
decnum tmp(x);
tmp.sign = 0;
return tmp;
}
decnum pow(const decnum& x, int n)
{
decnum tmp(1), fac(x);
for(; n>0; n>>=1) {
if(n&0x01)
tmp *= fac;
fac *= fac;
}
return tmp;
}
char decnum::root_1(int n)
{
char r = (int)(pow(1+val[num-1], 1.0/n) * pow(10,(num-1.0)/n));
for(; r>0 && pow(decnum(r), n) > *this; r--);
return r;
}
bool decnum::ispow(int n, decnum& r) const
{
if(num == 0) {
r.num = 0;
return true;
}
if(sign == 1 && (n&1 == 0)) {
r.num = 0;
return false;
}
decnum tmp, p;
r.cap = r.num = (num+n-1) / n;
r.val = new char[r.num];
r.sign = sign;
memset(r.val, 0, r.num);
tmp.val = val + (r.num-1)*n;
tmp.num = num - (r.num-1)*n;
r.val[r.num-1] = tmp.root_1(n);
tmp.val = new char[r.num+1];
tmp.cap = r.num+1;
int v;
p = pow(r, n);
if(p == *this) return true;
for(int i=r.num-2; i>=0; i--) {
memset(tmp.val, 0, i+1);
tmp.val = 1;
tmp.num = i+1;
tmp += r;
p = (*this - p) / (pow(tmp, n) - p);
if(p.num > 1)
v = 9;
else if(p.num > 0)
v = p.val[0];
else
v = 0;
for(; v>=0; v--) {
r.val = v;
p = pow(r, n);
if(p == *this)
return true;
if(p < *this)
break;
}
}
return false;
}
bool decnum::ispow() const
{
decnum r, dec2("2", 1);
if(ispow(2, r)) return true;
for(int n=3; r > dec2; n+=2) {
if(ispow(n, r)) return true;
}
return false;
}
decnum
root(const decnum& x, int n)
{
decnum r;
x.ispow(n, r);
return r;
}
decnum
div(const decnum& x, const decnum& y, decnum& r)
{
char ch, carry, fac;
decnum d = x, tmp;
int i;
if(y.num == 0) return x;
if(d.num < y.num) {
r = x;
d = 0;
return d;
}
char *newval = new char[d.num - y.num + 1];
memset(newval, 0, d.num - y.num + 1);
carry = 0;
fac = y.val[y.num-1] + 1;
tmp.val = d.val + d.num - y.num + 1;
tmp.num = y.num - 1;
for(i=d.num-1; i>= y.num-1; i--) {
tmp.val--;
tmp.num++;
ch = (carry * 10 + d.val) / fac;
tmp -= y * ch;
while(tmp >= y) {
tmp -= y;
ch++;
}
newval[i-y.num+1] = ch;
carry = d.val;
}
r = tmp;
tmp.val = NULL;
for(i=d.num-y.num+1; i>0 && newval[i-1] == 0; i--);
d.num = i;
delete[] d.val;
d.val = newval;
return d;
}
bool operator==(const decnum& x, const decnum&y)
{
if(x.sign != y.sign) return false;
if(x.num != y.num) return false;
for(int i=0; i < x.num; i++)
if(x.val != y.val)
return false;
return true;
}
bool operator!=(const decnum& x, const decnum&y)
{
return !(x==y);
}
bool operator>(const decnum& x, const decnum&y)
{
if(x.sign > y.sign) return false;
if(x.sign < y.sign) return true;
bool retval = (x.sign == 0);
if(x.num > y.num) return retval;
if(x.num < y.num) return !retval;
for(int i=x.num-1; i >= 0; i--)
if(x.val > y.val)
return retval;
else if(x.val < y.val)
return !retval;
return false;
}
bool operator<(const decnum& x, const decnum&y)
{
return y > x;
}
bool operator>=(const decnum& x, const decnum&y)
{
if(x.sign > y.sign) return false;
if(x.sign < y.sign) return true;
bool retval = (x.sign == 0);
if(x.num > y.num) return retval;
if(x.num < y.num) return !retval;
for(int i=x.num-1; i >= 0; i--)
if(x.val > y.val)
return retval;
else if(x.val < y.val)
return !retval;
return true;
}
bool operator<=(const decnum& x, const decnum&y)
{
return y >= x;
}
ostream& operator<<(ostream&os, const decnum& x)
{
if(x.size() == 0)
os << 0;
else {
if(x.sign == 1)
os << "-";
for(int i = x.size()-1; i>=0; i--)
os << (int)x.val;
}
return os;
}
[ 本帖最后由 yuxh 于 2006-8-23 18:11 编辑 ]
flw 回复于:2006-08-18 13:16:14
传说中的沙发?
zengjin8310 回复于:2006-08-18 13:18:14
8错, 对我搞科学计算有用, 测试过效率么?
zengjin8310 回复于:2006-08-18 13:21:30
最好再加上超高精度的浮点数的混合运算支持
yuxh 回复于:2006-08-18 13:26:58
这个本来是为大素数的测试用的,这些是要用到的基本运算
可惜我的工作与加密算法无关,纯粹是业余爱好,代码也是业余水平的。
就效率而言,比较慢的就是求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 编辑 ]
默难 回复于:2006-08-18 15:00:41
支持原创
顶一下吧
aple_smx 回复于:2006-08-19 15:25:25
come on
mirnshi 回复于:2006-08-21 15:02:15
接口为10进制, 内部的进制采用unsigned long或unsigned short,是不是更能借助逻辑运算,提高效率?
hqxyn 回复于:2006-08-22 10:29:15
来凑凑热闹 decimal.h /*************************************************************************** decimal.h - description ------------------- begin : Wed Jan 9 2002 copyright : (C) 2002 by Xian Yining email : [email]hqxyn@yahoo.com.cn[/email] ***************************************************************************/
/*************************************************************************** * * * 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)?MINUS:PLUS);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::ostream& operator <<(std::ostream&,const decimal&) ; //unsigned int midDigits(const decimal& ,const decimal& ) ;
#endif //DECIMAL_H
[ 本帖最后由 hqxyn 于 2006-8-22 19:54 编辑 ]
hqxyn 回复于:2006-08-22 10:31:52
money.h /*************************************************************************** decimal.cpp - description ------------------- begin : Wed Jan 9 2002 copyright : (C) 2002 by Xian Yining email : [email]hqxyn@yahoo.com.cn[/email] ***************************************************************************/
/*************************************************************************** * * * 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 编辑 ]
hqxyn 回复于:2006-08-22 10:35:03
decimal.cpp /*************************************************************************** decimal.cpp - description ------------------- begin : Wed Jan 9 2002 copyright : (C) 2002 by Xian Yining email : [email]hqxyn@yahoo.com.cn[/email] ***************************************************************************/
/*************************************************************************** * * * 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. * * * ***************************************************************************/ #include <iostream> #include <string>
#undef __DEBUG__ //#define __DEBUG__
#include "decimal.h" unsigned int midDigits(const decimal& ,const decimal& ) ;
/*********** * 构造函数 * ***********/ decimal::decimal(const std::string &s,const unsigned int p,const unsigned int d) { decimal x(s.c_str(),p,d); sn=x.sn; val=x.val; exp=x.exp; st=x.st; pre=x.pre; dec=x.dec; this->decReg(); if (val.size()>p) {st=OVERDIGITS;/*throw*/ ;} } decimal::decimal(const char* ci,const unsigned int p,const unsigned int d) { char c[strlen(ci)+1]; unsigned j=0; int i; strcpy(c,ci); #ifdef __DEBUG__ std::cout<<"char*:c="<<c<<"\n"; #endif //消前后空格 for ( i=strlen(c)-1;i>=0;--i ) { if ( c!=' ' ) break; c='\0'; } for ( j=0;j<strlen(c); ) { if (c[j]!=' ') break; ++j; } //判符号 if ( c[j]=='+' ) {sn=PLUS;++j;} else { if ( c[j]=='-' ) {sn=MINUS;++j;} else sn=PLUS; } //去前导‘0’ while (j<strlen(c+j)) {if (c[j]!='0') break;++j;} #ifdef __DEBUG__ std::cout<<"char*:j="<<c+j<<"\n"; #endif char *fp=c+j; //尾数数组指针 #ifdef __DEBUG__ std::cout<<"char*:fp="<<fp<<"\n"; #endif char *ep=NULL; //指数数组指针 char *dp=NULL; //小数数组指针 st=OK; for ( j=0;j<strlen(fp) && fp[j]!='\0'; ) { //取尾数整数部分 switch(fp[j]) { case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':++j;break; case '.':dp=fp+j+1;fp[j]='\0';break; case 'E':case 'e':ep=fp+j+1;fp[j]='\0';break; default:st=NOINIT;fp[j]='\0';
} } #ifdef __DEBUG__ std::cout<<"char*:fp2="<<fp<<"\n"; #endif if ( dp!=NULL ) { //取尾数小数部分 for (j=0;j<strlen(dp) && dp[j]!='\0';){ switch(dp[j]) { case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':++j;break; case 'E':case 'e':ep=dp+j+1;dp[j]='\0';break; default:st=NOINIT;dp[j]='\0'; } } } #ifdef __DEBUG__ std::cout<<"char*:fp3="<<ep<<"\n"; #endif if ( ep!=NULL ) { switch(ep[0]) { //检查指数首字符 case '+':case '-': case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':break; default:st=NOINIT; } } #ifdef __DEBUG__ std::cout<<"char*:fp4="<<fp<<"\n"; #endif if ( ep!=NULL ) { //取指数部分 for (j=1;j<strlen(ep);){ switch(ep[j]) { case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':++j;break; default:st=NOINIT; } #ifdef __DEBUG__ std::cout<<"char*:fp5c="<<fp[j]<<"\n"; #endif
} } #ifdef __DEBUG__ std::cout<<"char*:fp5="<<fp<<"\n"; #endif if (fp!=NULL ) { val=fp; } exp=0; if (dp!=NULL) { val.append(dp); exp-=strlen(dp); } if (ep!=NULL) { #ifdef __DEBUG__ std::cout<<"char*:*ep="<<atoi(ep)<<"\n"; #endif exp+=atoi(ep); } dec=d; pre=p; this->decReg(); if (val.size()>p) {st=OVERDIGITS;/*throw*/ ;} } decimal::decimal(const int v,const unsigned int p,const unsigned int d) { char c[std::numeric_limits<int>::digits10+2]; sprintf(c,"%i",v); #ifdef __DEBUG__ std::cout<<"int:c="<<c<<"\n"; #endif if (c[0]=='-') {sn=MINUS;val=c+1;} else {sn=PLUS;val=c;} pre=p; dec=d; exp=0; st=OK; this->decReg(); if (val.size()>p) {st=OVERDIGITS;/*throw*/ ;} } decimal::decimal(const unsigned int v,const unsigned int p,const unsigned int d) { char c[std::numeric_limits<unsigned int>::digits10+2]; sprintf(c,"%u",v); #ifdef __DEBUG__ std::cout<<"Uint:c="<<c<<"\n"; #endif sn=PLUS; val=c; pre=p; dec=d; exp=0; st=OK; this->decReg(); if (val.size()>p) {st=OVERDIGITS;/*throw*/ ;} } decimal::decimal(const long v,const unsigned int p,const unsigned int d) { char c[std::numeric_limits<long>::digits10+2]; sprintf(c,"%li",v); #ifdef __DEBUG__ std::cout<<"long:c="<<c<<"\n"; #endif if (c[0]=='-') {sn=MINUS;val=c+1;} else {sn=PLUS;val=c;} pre=p; dec=d; exp=0; st=OK; this->decReg(); if (val.size()>p) {st=OVERDIGITS;/*throw*/ ;} } decimal::decimal(const long long v,const unsigned int p,const unsigned int d) { char c[std::numeric_limits<long long>::digits10+2]; sprintf(c,"%lli",v); #ifdef __DEBUG__ std::cout<<"long long:c="<<c<<"\n"; #endif if (c[0]=='-') {sn=MINUS;val=c+1;} else {sn=PLUS;val=c;} pre=p; dec=d; exp=0; st=OK; this->decReg(); if (val.size()>p) {st=OVERDIGITS;/*throw*/ ;} } decimal::decimal(const unsigned long v,const unsigned int p,const unsigned int d) { char c[std::numeric_limits<unsigned int>::digits10+2]; sprintf(c,"%lu",v); #ifdef __DEBUG__ std::cout<<"Ulong:c="<<c<<"\n"; #endif val=c; sn=PLUS; pre=p; dec=d; exp=0; st=OK; this->decReg(); if (val.size()>p) {st=OVERDIGITS;/*throw*/ ;} }
decimal::decimal(const unsigned long long v,const unsigned int p,const unsigned int d) { char c[std::numeric_limits<unsigned long long>::digits10+2]; sprintf(c,"%llu",v); #ifdef __DEBUG__ std::cout<<"UUlong:c="<<c<<"\n"; #endif val=c; sn=PLUS; pre=p; dec=d; exp=0; st=OK; this->decReg(); if (val.size()>p) {st=OVERDIGITS;/*throw*/ ;} } decimal::decimal(const double v,const unsigned int p,const unsigned int d) { char c[std::numeric_limits<double>::digits10+std::numeric_limits<int>::digits10+1];
char t[10],s[15]="%."; sprintf(t,"%u",std::numeric_limits<double>::digits10); strcat(s,t); strcat(s,"E"); sprintf(c,s,v); #ifdef __DEBUG__ std::cout<<"double:c="<<c<<"\n"; #endif char *tE=strchr(c,'E'); if ( tE!=NULL ) { //取指数 exp=atoi(tE+1); *tE='\0'; } else exp=0; // for (unsigned u=strlen(c)-1;u>0 && c[u]=='0';c[u]='\0',u--) {} char *tD=strchr(c,'.'); if ( tD!=NULL ) { //将尾数变为整数,并相应调整指数 char *px=tD; for (;*(px+1)!='\0';*px = *(px+1),--exp,++px) {} *px='\0'; }
if (c[0]=='-') {sn=MINUS;val=c+1;} else {sn=PLUS;val=c;} pre=p; dec=d; st=OK; this->decReg(); if (val.size()>p) {st=OVERDIGITS;/*throw*/ ;} } decimal::decimal(const long double v,const unsigned int p,const unsigned int d) { char c[std::numeric_limits<long double>::digits10+std::numeric_limits<int>::digits10+1];
char t[10],s[15]="%."; sprintf(t,"%u",std::numeric_limits<long double>::digits10); strcat(s,t); strcat(s,"LE"); sprintf(c,s,v); #ifdef __DEBUG__ std::cout<<"long double:c="<<c<<"\n"; #endif char *tE=strchr(c,'E'); if ( tE!=NULL ) { //取指数 exp=atoi(tE+1); *tE='\0'; } else exp=0; // for (unsigned u=strlen(c)-1;u>0 && c[u]=='0';c[u]='\0',u--) {} char *tD=strchr(c,'.'); if ( tD!=NULL ) { //将尾数变为整数,并相应调整指数 char *px=tD; for (;*(px+1)!='\0';*px = *(px+1),--exp,++px) {} *px='\0'; } if (c[0]=='-') {sn=MINUS;val=c+1;} else {sn=PLUS;val=c;} pre=p; dec=d; st=OK; this->decReg(); if (val.size()>p) {st=OVERDIGITS;/*throw*/ ;} } /************ * 赋值操作符 * ************/ decimal& decimal::operator=(const decimal& d) { //精度定义(pre)和保留小数位数(dec)在变量定义时确定,?新值时不变。 #ifdef __DEBUG__ std::cout<<"in decimal[=]:"<<*this<<";;"<<d<<"\n"; #endif sn=d.sn; val=d.val; exp=d.exp; if (val.size()>pre) {st=OVERDIGITS;/*throw*/ ;} else st=d.st; return *this; } /************** * 算术运算符 * **************/ decimal& decimal::operator +=(const decimal& d2) { if (sn==d2.sn) { valAdd(val,exp,d2.val,d2.exp); } else { if (valCmp(val,exp,d2.val,d2.exp)<0) { std::string t=d2.val; int et=d2.exp; valSub(t,et,val,exp);val=t;exp=et;sn=d2.sn; } else valSub(val,exp,d2.val,d2.exp); } return this->decReg(); } decimal& decimal::operator -=(const decimal& d2) { if (sn==d2.sn) { if (valCmp(val,exp,d2.val,d2.exp)<0) { std::string t=d2.val; int et=d2.exp; valSub(t,et,val,exp);val=t;exp=et; sn=(d2.sn==PLUS)?MINUS:PLUS; } else valSub(val,exp,d2.val,d2.exp); } else { valAdd(val,exp,d2.val,d2.exp); } return this->decReg(); } decimal& decimal::operator *=(const decimal& d2) { sn=(sn==d2.sn)?PLUS:MINUS; exp+=d2.exp; valMult(val,d2.val); return this->decReg(); } decimal& decimal::operator /=(const decimal& d2) { if (d2.zero()) {st=UPFLOW;return *this;} sn=(sn==d2.sn)?PLUS:MINUS; int te1,te2; te1=exp+val.size();te2=d2.exp+d2.val.size(); te1-=te2; valDiv(val,d2.val,pre+1); exp=-val.size()+1+te1; return this->decReg(); } decimal operator +(const decimal& d1,const decimal& d2) { decimal d(0,midDigits(d1,d2),(d1.getDec()>=d2.getDec())?d1.getDec():d2.getDec()); d=d1; #ifdef __DEBUG__ std::cout<<"[+]:d="<<d<<"d.pre="<<d.getPre()<<"\n"; #endif return d+=d2; } decimal operator -(const decimal& d1,const decimal& d2) { decimal d(0,midDigits(d1,d2),(d1.getDec()>=d2.getDec())?d1.getDec():d2.getDec()); d=d1; #ifdef __DEBUG__ std::cout<<"[-]:d="<<d<<"d.pre="<<d.getPre()<<"\n"; #endif return d-=d2; } decimal operator *(const decimal& d1,const decimal& d2) { decimal d(0,d1.getPre()+d2.getPre(),d1.getDec()+d2.getDec()); d=d1; #ifdef __DEBUG__ std::cout<<"[*]:d="<<d<<"d.pre="<<d.getPre()<<"\n"; #endif return d*=d2; } decimal operator /(const decimal& d1,const decimal& d2) { decimal d(0,d1.getPre()+d2.getPre(),d1.getDec()+d2.getDec()); d=d1; #ifdef __DEBUG__ std::cout<<"[/]:d="<<d<<"d.pre="<<d.getPre()<<"\n"; #endif return d/=d2; } /********************** * 比较运算符 * *********************/
bool decimal::le(const decimal& d2) const { if (sn==decimal::PLUS && d2.sn==decimal::MINUS) return false; if (sn==decimal::MINUS && d2.sn==decimal::PLUS) return true; int r=decimal::valCmp(val,exp,d2.val,d2.exp); if (sn==decimal::PLUS && r<0) return true; if (sn==decimal::MINUS && r>0) return true; return false; } bool decimal::eq(const decimal& d2) const { if ((sn==decimal::MINUS && d2.sn==decimal::PLUS) || (sn==decimal::PLUS && d2.sn==decimal::MINUS)) return false; int r=decimal::valCmp(val,exp,d2.val,d2.exp); if (r==0) return true; return false; } bool decimal::gt(const decimal& d2) const { if (this->sn==decimal::MINUS && d2.sn==decimal::PLUS) return false; if (this->sn==decimal::PLUS && d2.sn==decimal::MINUS) return true; int r=decimal::valCmp(val,exp,d2.val,d2.exp); if (this->sn==decimal::PLUS && r>0) return true; if (this->sn==decimal::MINUS && r<0) return true; return false; }
bool operator <(const decimal& d1,const decimal& d2) { return d1.le(d2); } bool operator ==(const decimal& d1,const decimal& d2) { return d1.eq(d2); } bool operator >(const decimal& d1,const decimal& d2) { return d1.gt(d2); } bool operator <=(const decimal& d1,const decimal& d2) { return !(d1>d2); } bool operator >=(const decimal& d1,const decimal& d2) { return !(d1<d2); } bool operator !=(const decimal& d1,const decimal& d2) { return !(d1==d2); }
/***************** * 输入输出流 * ****************/ std::ostream &operator <<(std::ostream &os,const decimal& d) { #ifdef __DEBUG__ os<<"ok="<<d.ok(); os<<",sign="<<((d.getSn()==decimal::PLUS)?'+':((d.getSn()==decimal::MINUS)?'-':'?')); os<<",val="<<d.getVal(); os<<",exp="<<d.getExp(); os<<",pre="<<d.getPre(); os<<",dec="<<d.getDec(); os<<"\n"; #endif os<<d.toString(0,d.getDec()); return os; } /* std::istream& operator >>(std::istream& is,decimal& d) { std::string s; std::cin>>s; decimal dx(s.c_str()); d=dx; return is; } */ /************** * 杂函数 * **************/ std::string decimal::toEString(const unsigned len) const { std::string s=""; s.append((sn==decimal::MINUS)?"-":((sn==decimal::PLUS)?" ":"?")); s.append(val); s.append("E"); char c[50]; sprintf(c,"%i",exp); s.append(c); if (len != 0 && len<s.size()) s.assign(len,'*'); return s; } std::string decimal::toShortStr() const{ std::string s=toString(); if (s.find('.')==std::string::npos) return s; int c=0; for (uint u=s.length()-1;u>0;--u){ if (s[u]=='0') ++c; else break; } if (s[s.length()-1-c]=='.') ++c; s=s.substr(0,s.length()-c); return s; }
std::string decimal::toString() const{ return toString(0,getDec()); } std::string decimal::toString(const unsigned int len,const int de) const { std::string s=""; if ( ! this->ok() ) return s.append((len==0)?1:len,'*'); //数字无效 s.append((sn==decimal::MINUS)?"-":((sn==decimal::PLUS)?" ":"?")); if (exp>=0) { //整数 s.append(val).append(exp,'0').append(1,'.').append(de,'0'); } else { if (-exp>=val.size()) { //纯小数 s.append("0.").append(-exp-val.size(),'0').append(val); } else { s.append(val.substr(0,val.size()+exp)); s.append(1,'.'); std::string x=val.substr(val.size()+exp); s.append(x); //带小数 s.append((de>x.size())?de-x.size():0,'0'); } } if (len != 0 && len<s.size()) s.assign(len,'*'); return s; } decimal& decimal::round() { return round(dec); } decimal& decimal::round(int r) { if (r<-exp) { //末位属于舍入位 std::string x="5"; int e=-(r+1); valAdd(val,exp,x,e); int i=-exp-r; if ((val.size()-i)<=0) val="0"; else val=val.substr(0,val.size()-i); exp+=i; } return this->decReg(); }
decimal round(const decimal& d,const int dec) { decimal dx(0,d.getPre(),dec); dx=d; dx.round(dec); return dx; }
/**************** * 内部子程序 * ****************/ void decimal::valDiv(std::string& s1,const std::string& s2,const unsigned len) { std::string s(len,'0'); //商 int ed=s2.size()-s1.size(); //商的小数位数 std::string t1=s1,t2=s2; int et1; //被除数对位指数,把两数首位对齐 et1=ed; unsigned int i; //商数循环 int c; //借位 for (i=0;i<len;++i,++et1) { int j=1; for (j=1;j<=10;++j) { if (valCmp(t1,et1,s2,0)<0) { --j; break; } c=valSub(t1,et1,s2,0) ; } s=char(j+48); } s1=s; } char decimal::valMult(std::string& s1,const std::string& s2) { std::string s="0"; int es=0; for (unsigned int i=0;i<s2.size();++i) { //乘数从末尾向前循环 char c1,c2=s2[s2.size()-1-i],m='0'; int j; std::string pn(s1.size()+1,'0'); for (j=s1.size()-1;j>=0;--j) { //被乘数乘以当前乘数位 c1=s1[j]; m=digitMult(c1,c2,m); pn[j+1]=c1; } es=-i; pn[0]=m; valAdd(s,es,pn,0); } if (s[0]!='0') s1=s; else s1=s.substr(1); return '0'; } int decimal::valSub(std::string& s1,int &e1,const std::string& s2,const int e2) { //计算差的位数 //std::cout<<"s1="<<s1<<",e1="<<e1<<",s2"<<s2<<",e2="<<e2<<"\n"; int li1,ld1,li2,ld2,li,ld; li1= s1.size()+e1; if ( e1>=0 ) { li1=s1.size()+e1; ld1=0; } else { if (li1<0) li1=0; ld1=-e1; } li2=s2.size()+e2; if ( e2>=0 ) { ld2=0; } else { if (li2<0) li2=0; ld2=-e2; } li=(li1>=li2)?li1:li2; //整数位数 ld=(ld1>=ld2)?ld1:ld2; //小数位数 std::string s(li+ld,'0'); int qb1, //第一串首位权数 qe1, //第一串末位权数 qb2, //第二串首位权数 qe2; //第二串末位权数 qe1=li-e1-1;qb1=qe1-s1.size()+1; qe2=li-e2-1;qb2=qe2-s2.size()+1; char c1,c2; int m=0,j; for (j=li+ld-1;j>=0;--j) { c1=(j>=qb1 && j<=qe1)?s1[j-qb1]:'0'; c2=(j>=qb2 && j<=qe2)?s2[j-qb2]:'0'; m=digitSub(c1,c2,m); s[j]=c1; } s[0]=c1; s1=s;e1=-ld; return m; } void decimal::valAdd(std::string& s1,int &e1,const std::string& s2,const int e2) { //计算和的位数 int li1,ld1,li2,ld2,li,ld; li1= s1.size()+e1; if ( e1>=0 ) { li1=s1.size()+e1; ld1=0; } else { if (li1<0) li1=0; ld1=-e1; } li2=s2.size()+e2; if ( e2>=0 ) { ld2=0; } else { if (li2<0) li2=0; ld2=-e2; } li=(li1>=li2)?li1:li2; //整数位数 ld=(ld1>=ld2)?ld1:ld2; //小数位数 std::string s(li+ld+1,'0'); int qb1, //第一串首位权数 qe1, //第一串末位权数 qb2, //第二串首位权数 qe2; //第二串末位权数 qe1=li-e1;qb1=qe1-s1.size()+1; qe2=li-e2;qb2=qe2-s2.size()+1; char c1,c2; int m=0,j; for (j=li+ld;j>0;--j) { c1=(j>=qb1 && j<=qe1)?s1[j-qb1]:'0'; c2=(j>=qb2 && j<=qe2)?s2[j-qb2]:'0'; m=digitAdd(c1,c2,m); s[j]=c1; } if (m>0) {s[0]='1';s1=s;} else s1=s.substr(1); e1=-ld; } int decimal::digitAdd(char& c1,const char c2,const int car) { int i=c1+c2-48+car; int c=0; if (i>57) {i-=10;c=1;} c1=char(i);return c; } int decimal::digitSub(char& c1,const char c2,const int b) { int c=(c1>=c2+b)?0:1; int i=c1+(c*10)-c2+48-b; c1=char(i); return c; } char decimal::digitMult(char& c1,const char c2,const char m) { int i=(c1-48)*(c2-48)+(m-48); c1=i%10+48; return char(i/10+48); } int decimal::valCmp(const std::string& s1,const int e1,const std::string& s2,const int e2) const { unsigned int h1,h2; //第一有效位的位置 //去掉前导0 for (h1=0;h1<s1.size() && (s1[h1]=='0');++h1) {} for (h2=0;h2<s2.size() && (s2[h2]=='0');++h2) {} if ( (h1<s1.size()) && ((s1.size()-h1+e1)>(s2.size()-h2+e2)) ) return 1; if ( ((s1.size()-h1+e1)<(s2.size()-h2+e2)) && (h1<s1.size()) ) return -1; int i,j; for (i=s1.size()-h1,j=s2.size()-h2;i>0 && j>0;--i,--j,++h1,++h2) {
if (s1[h1]<s2[h2]) return -1; if (s1[h1]>s2[h2]) return 1; } if (i>j) { for (;i>0 && s1[h1]=='0';--i,++h1) {} return (i==0)?0:1; } if (i<j) { for (;j>0 && s2[h2]=='0';--j,++h2) {} return (j==0)?0:-1; } return 0; }
decimal& decimal::decReg() { //消去前0和尾0,调整指数exp unsigned int b,e; for (b=0;b<val.size()-1 && val=='0';++b){} for (e=val.size()-1;e>b && val[e]=='0';--e,++exp){} if (b!=0 || e!=val.size()-1) val=val.substr(b,e-b+1); if (val.size()==1 && val[0]=='0') {exp=0;sn=PLUS;} //值为“零”,指数应为0,符号认定为正 return *this; } unsigned int midDigits(const decimal& d1,const decimal& d2) { //计算和或差中间变量的位数 int li1,ld1,li2,ld2,li,ld; li1= d1.getVal().size()+d1.getExp(); if ( d1.getExp()>=0 ) { li1=d1.getVal().size()+d1.getExp(); ld1=0; } else { if (li1<0) li1=0; ld1=-d1.getExp(); } li2=d2.getVal().size()+d2.getExp(); if ( d2.getExp()>=0 ) { ld2=0; } else { if (li2<0) li2=0; ld2=-d2.getExp(); } li=(li1>=li2)?li1:li2; //整数位数 ld=(ld1>=ld2)?ld1:ld2; //小数位数 return li+ld+1; }
[ 本帖最后由 hqxyn 于 2006-8-22 19:55 编辑 ]
flw 回复于:2006-08-22 10:36:00
引用:原帖由 mirnshi 于 2006-8-21 15:02 发表
接口为10进制, 内部的进制采用unsigned long或unsigned short,是不是更能借助逻辑运算,提高效率?
我也这样想。
考虑到 unsigned int 在 32 位机上可以表示超过 10 亿的整数,因此倘若采用万进制来进行内部表示的话,效率应该会高很多。
至于加减法,可以直接用亿进制来进一步提高速度。
hqxyn 回复于:2006-08-22 10:56:17
开始我也曾用long long型作内部表示,但出于以下考虑,还是放弃了
1)要能表示”任意“大小的十进浮点数。
2)算术运算不能带来误差(用二进制数表示十进制小数总会有舍入误差)。
当然用字符型处理数值效率确实低,但这样作的最直接用途是处理货币类应用,并不是科学计算,也就将就了。
soaact 回复于:2006-08-22 11:36:17
弱弱的问一下楼主:
您在做除法和乘方的时候采用的是什么算法,没有看太明白?
谢谢:)
yuxh 回复于:2006-08-22 12:30:32
我写这个类的目的是想实现判断一个数是否是素数, 其中第一步就是判断这个数是否某个数的整数次幂
所以我关心的是运算的效率,而不是把它扩展成浮点数形式等更适用的情况
由于在推导一些公式时就是用10进制来考虑的,所以写的代码里也是用10进制数表示的,其实,对代码作一些相应的改动,是很方便换成16进制或别的基进制,(也可以扩展成浮点数的形式,但对我的应用来说,意义不大).
[ 本帖最后由 yuxh 于 2006-8-22 12:38 编辑 ]
yuxh 回复于:2006-08-22 13:04:39
贴一段测试代码给大家玩玩:D
#include "decnum.h"
int main()
{
decnum x, y, r;
char *line = NULL;
size_t n = 0;
int read;
cout << "input x:" << endl;
if((read = (int)getline(&line, &n, stdin)) != -1) {
x = decnum(line, read-1);
}
else
exit(-1);
cout << "input y:" << endl;
if((read = (int)getline(&line, &n, stdin)) != -1) {
y = decnum(line, read-1);
}
else
exit(-1);
cout << "x = " << x << endl;
cout << "y = " << y << endl;
cout << "x * y =" << x * y << endl;
cout << "x / y =" << x / y << endl;
cout << "x % y =" << x % y << endl;
cout << "div(x, y) =" << div(x , y, r) << endl;
cout << "mod(x, y) =" << r << endl;
cout << "y ^ 2 =" << pow(y, 2) << endl;
cout << "x ^ 1/2 =" << root(x, 2) << endl;
cout << "x is pow = " << x.ispow() << endl;
return 0;
}
引用:input x:
12934891238741902347120934871230948712390487123904871239047812390847123094871230948712309487123904871230947123980471203948712309487120394712398471239048713256129834712903847120394781239084712930487231094712394087123094123481203333333333333333333333333333333333333333333888888888888888888888888888888888888888888888888222222222222222222222222222222222222221094387123908471293048721903487123908412903471290384712398471239847213984712938471209384172093847129834712093847123904123471290384712398471209348712093847120938471297340129341
input y:
87123904781239084712309487123094871230948712390487123
x = 12934891238741902347120934871230948712390487123904871239047812390847123094871230948712309487123904871230947123980471203948712309487120394712398471239048713256129834712903847120394781239084712930487231094712394087123094123481203333333333333333333333333333333333333333333888888888888888888888888888888888888888888888888222222222222222222222222222222222222221094387123908471293048721903487123908412903471290384712398471239847213984712938471209384172093847129834712093847123904123471290384712398471209348712093847120938471297340129341
y = 87123904781239084712309487123094871230948712390487123
x * y =1126938232639833173075933852454844491172426928514059866807740841770815249456423275828974308682129087476539239375374114934208988211619943619716558347499808789403504191997992053251495407207133672212198009872845450749525122406765537233683189166639249361344448037097903846536903047332910602617949715068386039572749284661323652396812507276858460341917936752512602597008627491342253724797935606421392773895578442187710885039658694980497445673861077574294718176507864939038642062979105391800654254681231524754223749316701123751673470225808955075291647887679573776980478625133783450814975943
x / y =148465467327484275048232812439334306695533671227089122007816650126394502951501427671718661140385906942393209068225081817296775831986299773922335101921640962699307587052445014486841122328740344708845214812651256032481988250472736002705523700302442398432754627409724200156670159012028113430398315975429449502269548763370786332836604219524721316400456079938591537603272259855595623013801608933716962712146970686555106278637839124034044858476557783789374654839217122223912234300207
x % y =79300951666803804539185154310166594060311523590394880
div(x, y) =148465467327484275048232812439334306695533671227089122007816650126394502951501427671718661140385906942393209068225081817296775831986299773922335101921640962699307587052445014486841122328740344708845214812651256032481988250472736002705523700302442398432754627409724200156670159012028113430398315975429449502269548763370786332836604219524721316400456079938591537603272259855595623013801608933716962712146970686555106278637839124034044858476557783789374654839217122223912234300207
mod(x, y) =79300951666803804539185154310166594060311523590394880
y ^ 2 =7590574784330414645380746230930586484532745231159928445672223588351361500455337820516206371351345228817129
x ^ 1/2 =3596510981318130543477927424759527967760623382196876121688918127992258229306117726707700713885454867164034990294666943466289844107281148419105171980209085534883218753821511324570335831894205011649807156193955342866243572062280023407886590191390520013437462254313721
x is pow = 0
思一克 回复于:2006-08-22 13:09:09
yuxh 弄了一个伟大的工程呀
yuxh 回复于:2006-08-22 13:12:12
引用:原帖由 思一克 于 2006-8-22 13:09 发表
yuxh 弄了一个伟大的工程呀
:D
只是玩玩,呵呵~万里长征才走了第一步哇~
xiaomiao 回复于:2006-08-22 15:16:57
搞科学计算最好不用C/C++,传统的用Fortran,现代流行的用Matlab,后者矩阵运算功能超级强大
aple_smx 回复于:2006-08-22 15:29:53
顶起
soaact 回复于:2006-08-22 15:44:32
引用:原帖由 xiaomiao 于 2006-8-22 15:16 发表
搞科学计算最好不用C/C++,传统的用Fortran,现代流行的用Matlab,后者矩阵运算功能超级强大
不同意您的意见!难道MATLAB不是用C/C++编写的么?
建议你去SF或BELLLAB看看,哪个科学计算用的语言是MATLAB?JAVA
倒是有的,偶尔也有PERL就是没有看见用MATLAB或MAPLE之类来做的。
为什么?效率太低了!
去你的系统上算一下:
2^1000000
看看是MATLAB快还是调用了gmp库的c/c++快!
另 to LZ :在计算pow(A,1/n)的时候还可以用另一个迭代公式:
a[k]=(A/pow(a[k-1],n-1) + (n-1)*a[k-1])/n
A和n是初始值
再次感谢lz
rushrush 回复于:2006-08-22 15:46:56
http://www.swox.com/gmp/ :em25:
醉卧水云间 回复于:2006-08-22 16:42:40
AKS早有人测试过了,不灵。
xiaomiao 回复于:2006-08-22 18:17:14
呵呵,你的说法有点道理,从效率和性能上看C/C++是占有优势,但Matlab一类的科学计算语言在易用性、直观性还有可视化等方面有很大优势,现在很多高校的工科自控、电子等专业不都用Matlab/Simulink一类的软件做计算和仿真嘛
yuxh 回复于:2006-08-23 18:17:04
增加了负数,但负数不支持取余(%)及相应的带余除法(div)
并用它解决了醉卧水云间 的pell方程的问题
:D
assiss 回复于:2006-08-23 18:29:11
你测试过你的大数库效率吗?
我曾经仔细优化我自己写的C大数库函数,但始终没有GMP的速度快。看GMP的代码,优化到了汇编地步。实在是恐怖。
zengjin8310 回复于:2006-08-24 08:29:33
引用:原帖由 yuxh 于 2006-8-22 12:30 发表
我写这个类的目的是想实现判断一个数是否是素数, 其中第一步就是判断这个数是否某个数的整数次幂
所以我关心的是运算的效率,而不是把它扩展成浮点数形式等更适用的情况
由于在推导一些公式时就是用10进制来考虑的,所以写的代码里也是用10进制数表示的,其实,对代码作一些相应的改动,是很方便换成16进制或别的基进制,(也可以扩展成浮点数的形式,但对我的应用来说,意义不大).
费马定理? 可以参考java RSA公私钥的生成算法, 我没研究过, 你看看那个素数寻找算法是不是比你的好
zengjin8310 回复于:2006-08-24 08:32:41
引用:原帖由 xiaomiao 于 2006-8-22 15:16 发表
搞科学计算最好不用C/C++,传统的用Fortran,现代流行的用Matlab,后者矩阵运算功能超级强大
matlab这个主要是给应用的人用, 科学计算是研究的东西跟matlab里面那一堆工具箱里面的算法实现类似的东西。 如果入门级科学计算matlab可以, 骨灰级的你不懂操作系统,不懂C/C++,lisp你给我试试看你能研究个啥
|