博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

double精确度。。。。。

Posted on 2011-12-07 15:56  ccmfc  阅读(642)  评论(0编辑  收藏  举报

#include <iostream>
using namespace std;

#define MAX_MUL_SIZE 256
#define MUL_SPRINTF 1
#define MUL_FRINED 1
#define DELETE(p) \
{\
if(p)\
{\
delete(p);\
p=NULL;\
}\
}
#define NEW_SET(p,ch,size) \
{\
p=new char[size];\
memset(p, ch, size);\
}
#define CLS_STRCH(p) \
{\
if(back_strch(p, '.'))\
{\
cls_back_strch(p);\
}\
cls_front_strch(p);\
}
#define TWO_REVERSE(p1, p2) \
{\
reverse(p1);\
reverse(p2);\
}
#define TWO_DELETE(p1,p2) \
{\
DELETE(p1);\
DELETE(p2);\
}
#define TWO_NEW_SET(p1,p2,ch,size) \
{\
NEW_SET(p1, ch, size);\
NEW_SET(p2, ch, size);\
}
#define MAX(a,b) ((a)>(b)?(a):(b))
#define NEW_NUM 4 /* 符号 小数点 结束标志符*/
class Double
{
public:
Double();
Double(const char&);
Double(const int&);
Double(const char*);
Double(const float&);
Double(const double&);
Double(const Double&);
virtual ~Double();
//
Double& operator+(const Double&);
Double& operator+=(const Double&);
Double& operator-(const Double&);
Double& operator-=(const Double&);
Double& operator*(const Double&);
Double& operator*=(const Double&);
Double& operator/(const Double&);
Double& operator/=(const Double&);
Double& operator%(const Double&);
Double& operator ++();
Double& operator ++(int);
Double& operator --();
Double& operator --(int);
Double& operator -();
int operator>(const Double&);
int operator>=(const Double&);
int operator==(const Double&);
int operator<(const Double&);
int operator<=(const Double&);
//in out
#if MUL_FRINED
friend istream& operator>>(istream&,Double&);
friend ostream& operator<<(ostream&,const Double&);
#else
istream& operator>>(istream&);
ostream& operator<<(ostream&);
#endif
public:
char* d_str();
int size()const;
Double& reverse();
char* reverse(char *pSrc);
int compare(const Double&);
int compare(const Double&, const Double&);
private:
void i_strch(char *pSrc1, char *pSrc2, const char ch);
void p_strch(char *pSrc1, char *pSrc2, const char ch);
void set_strch(char *pSrc1, char *pSrc2, const char ch);
char* cls_front_strch(char* pSrc);
char* cls_back_strch(char* pSrc);
char* front_strch(const char* pSrc, const char ch);
char* back_strch(const char* pSrc, const char ch);
char* sign_add_handle(char* pSrc1, char* pSrc2);
char* sign_sub_handle(char* pSrc1, char* pSrc2);
char* sign_mul_handle(char* pSrc1, char* pSrc2);
char* usign_add(char* pSrc1, char *pSrc2);
char* usign_sub(char* pSrc1, char *pSrc2);
char* usign_mul(char* pSrc1, char *pSrc2);
private:
// char *m_Src;
char m_Src[MAX_MUL_SIZE];
};
char* Double::d_str()
{
return (char*)this->m_Src;
}
int Double::size()const
{
return strlen(this->m_Src);
}
Double& Double::reverse()
{
if (this->size())
{
this->reverse(this->m_Src);
}
return *this;
}
char* Double::reverse(char *pSrc)
{
int i=0;
int len=strlen(pSrc);
if(NULL==pSrc)return NULL;
for (i=0; i<len/2; i++)
{
*(pSrc+i)^=*(pSrc+len-i-1);*(pSrc+len-i-1)^=*(pSrc+i);*(pSrc+i)^=*(pSrc+len-i-1);
}
return pSrc;
}
Double::Double()
{
//NEW_SET(this->m_Src, 0, MAX_MUL_SIZE);
memset(this->m_Src, 0, MAX_MUL_SIZE);
}
Double::~Double()
{
//DELETE(this->m_Src);
}
Double& Double::operator ++()
{
if(this->front_strch(this->m_Src,'-'))
{
*this-=1;
}
else
{
*this+=1;
}
return *this;
}
Double& Double::operator ++(int)
{
static Double tmp;

tmp=*this;
if(this->front_strch(this->m_Src,'-'))
{
*this-=1;
}
else
{
*this+=1;
}
return tmp;
}
Double& Double::operator --()
{
if(this->front_strch(this->m_Src,'-'))
{
*this-=1;
}
else
{
*this+=1;
}
return *this;
}
Double& Double::operator --(int)
{
static Double tmp;
tmp=*this;
if(this->front_strch(this->m_Src,'-'))
{
*this-=1;
}
else
{
*this+=1;
}
return tmp;
}
Double& Double::operator -()
{
int len=this->size();
char *pTmp=NULL;

NEW_SET(pTmp, 0, len+2);

if (NULL==this->front_strch(this->m_Src,'-'))
{
sprintf(pTmp, "%c%s", '-',this->m_Src);
}
else
{
int flags=(len-strlen(this->back_strch(this->m_Src,'-'))+1)%2;
if (flags) sprintf(pTmp, "%s", this->back_strch(this->m_Src,'-')+1);
else sprintf(pTmp, "%c%s", '-', this->back_strch(this->m_Src,'-')+1);
}

strcpy(this->m_Src, pTmp);
DELETE(pTmp);
return *this;
}

Double::Double(const char& ch)
{
// NEW_SET(this->m_Src, 0, MAX_MUL_SIZE);
#if MUL_SPRINTF
sprintf(this->m_Src, "%c", ch);
#else
this->m_Src[0]=ch;
#endif
}
Double::Double(const int& sh)
{
// NEW_SET(this->m_Src, 0, MAX_MUL_SIZE);
#if MUL_SPRINTF
sprintf(this->m_Src, "%d", sh);
#else
char* pTmp=this->m_Src;
int tmp=sh;
while (tmp)
{
*pTmp++=tmp%10+'0';
tmp/=10;
}
*pTmp='\0';
this->reverse();
#endif
}
Double::Double(const char* pSrc)
{
// NEW_SET(this->m_Src, 0, MAX_MUL_SIZE);
while(*pSrc && *pSrc=='0' && pSrc++);

#if MUL_SPRINTF
sprintf(this->m_Src, "%s", pSrc);
#else

#endif
}
Double::Double(const float& fl)
{
// NEW_SET(this->m_Src, 0, MAX_MUL_SIZE);
#if MUL_SPRINTF
sprintf(this->m_Src, "%f", fl);
#else
#endif
}
Double::Double(const double& db)
{
// NEW_SET(this->m_Src, 0, MAX_MUL_SIZE);
#if MUL_SPRINTF
sprintf(this->m_Src, "%lf", db);
#else
#endif
}
Double::Double(const Double& Obj)
{
strcpy(this->m_Src,Obj.m_Src);
}
#if MUL_FRINED
istream& operator >>(istream& in, Double& Obj)
{
memset(Obj.m_Src,0,MAX_MUL_SIZE);
in>>Obj.m_Src;
return in;
}
ostream& operator <<(ostream& out, const Double& Obj)
{
out<<Obj.m_Src;
return out;
}
#else
istream& Double::operator >>(istream& in)
{
memset(this->m_Src,0,MAX_MUL_SIZE);
in>>this->m_Src;
return in;
}
ostream& Double::operator <<(ostream& out)
{
out<<this->m_Src;
return out;
}
#endif
char* Double::front_strch(const char *pSrc, const char ch)
{
char *pTmp=(char*)pSrc;

while(*pTmp && *pTmp != ch && pTmp++);
if (pTmp==pSrc+strlen(pSrc)) return NULL;
else return (char*)pSrc+(int)(pTmp-pSrc);
}
char* Double::back_strch(const char *pSrc, const char ch)
{
char *pTmp=(char*)pSrc+strlen(pSrc);
while((pTmp!=pSrc-1) && *pTmp!=ch && pTmp--);
if (pTmp==pSrc-1)return NULL;
else return pTmp;
}
void Double::i_strch(char *pSrc1, char *pSrc2, const char ch)
{
int len1=strlen(pSrc1);
int len2=strlen(pSrc2);
char strch[MAX_MUL_SIZE]={0};

memset(strch, ch, MAX_MUL_SIZE);
if (len1 == len2);
else if (len1>len2)
{
this->reverse(pSrc2);
strncat(pSrc2, strch, len1-len2);
*(pSrc2+len1)='\0';
this->reverse(pSrc2);
}
else
{
this->reverse(pSrc1);
strncat(pSrc1, strch, len2-len1);
*(pSrc1+len2)='\0';
this->reverse(pSrc1);
}
}
void Double::p_strch(char *pSrc1, char *pSrc2, const char ch)
{
int len1=strlen(pSrc1);
int len2=strlen(pSrc2);
char *pTmp1=NULL;
char *pTmp2=NULL;
char *pTmpSrc1=NULL;
char *pTmpSrc2=NULL;
int len=MAX(len1, len2);
TWO_NEW_SET(pTmpSrc1,pTmpSrc2, 0, len+1);

//整数置0
len1=len1-strlen(front_strch(pSrc1,'.'));
len2=len2-strlen(front_strch(pSrc2,'.'));
len=MAX(len1,len2);

TWO_NEW_SET(pTmp1, pTmp2, 0, len+1);
strncpy(pTmp1, pSrc1, len1);
strncpy(pTmp2, pSrc2, len2);
i_strch(pTmp1, pTmp2, ch);
sprintf(pTmpSrc1,"%s%c", pTmp1, '.');
sprintf(pTmpSrc2,"%s%c", pTmp2, '.');

TWO_DELETE(pTmp1,pTmp2);
//小数
len1=strlen(front_strch(pSrc1,'.'))-1;
len2=strlen(front_strch(pSrc2,'.'))-1;
len=len1>len2?len1:len2;
TWO_NEW_SET(pTmp1, pTmp2, 0, len+1);
strncpy(pTmp1, (char*)(front_strch(pSrc1,'.')+1*sizeof(char)), len1);
strncpy(pTmp2, (char*)(front_strch(pSrc2,'.')+1*sizeof(char)), len2);
sprintf(pSrc1, "%s%s", pTmpSrc1,pTmp1);
sprintf(pSrc2, "%s%s", pTmpSrc2,pTmp2);

TWO_DELETE(pTmp1, pTmp2);
TWO_DELETE(pTmpSrc1, pTmpSrc2);
}
void Double::set_strch(char *pSrc1, char *pSrc2, const char ch)
{
char strch[MAX_MUL_SIZE]={0};
memset(strch, ch, MAX_MUL_SIZE);
if (!front_strch(pSrc1, '.') && !front_strch(pSrc2, '.'))
{
i_strch(pSrc1, pSrc2, ch);
}
else
{
if (front_strch(pSrc1, '.') && !front_strch(pSrc2, '.'))
{
int len=strlen(pSrc2);
*(pSrc2+len)='.';
*(pSrc2+len+1)='\0';
strncat(pSrc2, strch, strlen(front_strch(pSrc1, '.'))-1);
}
else if (!front_strch(pSrc1, '.') && front_strch(pSrc2, '.'))
{
int len=strlen(pSrc1);
*(pSrc1+len)='.';
*(pSrc1+len+1)='\0';
strncat(pSrc1, strch, strlen(front_strch(pSrc2, '.'))-1);
}
else
{
int len1=strlen(front_strch(pSrc1,'.'));
int len2=strlen(front_strch(pSrc2,'.'));
if (len1>len2)
{
strncat(pSrc2, strch, len1-len2);
}
else
{
strncat(pSrc1, strch, len2-len1);
}
}
p_strch(pSrc1, pSrc2, '0');
}
}
char* Double::cls_front_strch(char *pSrc)
{
char *pTmp=this->reverse(pSrc)+strlen(pSrc)-1;

while(*pTmp=='0' && (pTmp!=pSrc &&*(pTmp-1)!='.') && pTmp--);
*++pTmp='\0';
this->reverse(pSrc);
return pSrc;
}
char* Double::cls_back_strch(char *pSrc)
{
char *pTmp=pSrc+strlen(pSrc)-1;
while (*pTmp=='0' && (pTmp!=pSrc && *(pTmp-1)!='.') && pTmp--);

*++pTmp='\0';
return pSrc;
}
char* Double::usign_add(char *pSrc1, char *pSrc2)
{
int i=0;
int len=0;
this->set_strch(pSrc1, pSrc2, '0');

len=strlen(pSrc1);
TWO_REVERSE(pSrc1, pSrc2);

for (i=0; i<len; i++)
{
if ('.'!=*(pSrc1+i))
{
*(pSrc1+i)=*(pSrc1+i)+*(pSrc2+i)-'0';
if (*(pSrc1+i)>'9')
{
*(pSrc1+i)-=10;
if ('.'==*(pSrc1+i+1)) i++;
if(i+1!=len)*(pSrc1+i+1)+=1;
else *(pSrc1+i+1)='1';
}
}
}

TWO_REVERSE(pSrc1, pSrc2);
CLS_STRCH(pSrc1);
return pSrc1;
}
char* Double::sign_add_handle(char* pSrc1, char *pSrc2)
{
int len1=strlen(pSrc1);
int len2=strlen(pSrc2);
char *pTmp1=NULL;
char *pTmp2=NULL;
if (NULL==this->front_strch(pSrc1, '-') && NULL==this->front_strch(pSrc2, '-')) //正正
{
this->usign_add(pSrc1,pSrc2);
}
else if (this->front_strch(pSrc1, '-') && this->front_strch(pSrc2, '-'))//负负
{
TWO_NEW_SET(pTmp1, pTmp2, 0, MAX(len1,len2)+NEW_NUM);//len1+len2+2);
strcpy(pTmp1, this->front_strch(pSrc1, '-')+sizeof(char));
strcpy(pTmp2, this->front_strch(pSrc2, '-')+sizeof(char));
this->usign_add(pTmp1, pTmp2);
sprintf(pSrc1, "%c%s", '-', pTmp1);
}
else
{
TWO_NEW_SET(pTmp1, pTmp2, 0, MAX(len1,len2)+NEW_NUM);//len1+len2+2);
if (NULL==this->front_strch(pSrc1, '-') && this->front_strch(pSrc2, '-'))//正负
{
strcpy(pTmp1, pSrc1);
strcpy(pTmp2, this->front_strch(pSrc2, '-')+sizeof(char));
}
else //负正
{
strcpy(pTmp1, pSrc2);
strcpy(pTmp2, this->front_strch(pSrc1, '-')+sizeof(char));
}
this->set_strch(pTmp1,pTmp2, '0');
this->usign_sub(pTmp1, pTmp2);
strcpy(pSrc1, pTmp1);
}
TWO_DELETE(pTmp1, pTmp2);
CLS_STRCH(pSrc1);
return pSrc1;
}
// +=
Double& Double::operator +=(const Double& Obj)
{
char *pObj=NULL;
NEW_SET(pObj,0,MAX(this->size(),Obj.size())+NEW_NUM);
strcpy(pObj, Obj.m_Src);

this->sign_add_handle(this->m_Src, pObj);
DELETE(pObj);
return *this;
}
// +
Double& Double::operator +(const Double& Obj)
{
*this+=Obj;
return *this;
}
char* Double::usign_sub(char *pSrc1, char *pSrc2)
{
char flags=0; //0代表正1代码负数
int len=strlen(pSrc1);
int i=0;
char *pTmp1=NULL;
char *pTmp2=NULL;

TWO_NEW_SET(pTmp1, pTmp2, 0, len+NEW_NUM);
do
{
if (strcmp(pSrc1, pSrc2)>0)
{
strcpy(pTmp1, pSrc1);
strcpy(pTmp2, pSrc2);
}
else if (strcmp(pSrc1, pSrc2)==0)
{
sprintf(pSrc1, "%s", "0");
break;
}
else
{
flags=1;
strcpy(pTmp1, pSrc2);
strcpy(pTmp2, pSrc1);
}
TWO_REVERSE(pTmp1,pTmp2);
for (i=0; i<len; i++)
{
if ('.'!=*(pTmp1+i))
{
*(pTmp1+i)=*(pTmp1+i)-*(pTmp2+i)+'0';
if (*(pTmp1+i)<'0')
{
*(pTmp1+i)+=10;
if ('.'==*(pTmp1+i+1))i++;
*(pTmp1+i+1)-=1;
}
}
}
this->reverse(pTmp1);
CLS_STRCH(pTmp1);
if (flags)sprintf(pSrc1, "%c%s", '-', pTmp1);
else sprintf(pSrc1, "%s", pTmp1);
} while (0);
TWO_DELETE(pTmp1,pTmp2);
return pSrc1;
}
char* Double::sign_sub_handle(char *pSrc1, char *pSrc2)
{
char *pTmp1=NULL;
char *pTmp2=NULL;
int len1=strlen(pSrc1);
int len2=strlen(pSrc2);

if (this->front_strch(pSrc1, '-') && NULL==this->front_strch(pSrc2, '-')) //负负
{
NEW_SET(pTmp1, 0, MAX(len1,len2)+NEW_NUM);//len1+len2+2)
strcpy(pTmp1, this->front_strch(pSrc1, '-')+1);
this->usign_add(pTmp1,pSrc2);
sprintf(pSrc1, "%c%s", '-', pTmp1);
}
else if (NULL==this->front_strch(pSrc1, '-') && this->front_strch(pSrc2, '-')) //正正
{
this->usign_add(pSrc1, pSrc2);
}
else
{
TWO_NEW_SET(pTmp1, pTmp2, 0, MAX(len1,len2)+NEW_NUM);
if (NULL==this->front_strch(pSrc1, '-') && NULL==this->front_strch(pSrc2, '-'))//正负
{
strcpy(pTmp1, pSrc1);
strcpy(pTmp2, pSrc2);
}
else//负正
{
strcpy(pTmp1, this->front_strch(pSrc1,'-')+sizeof(char));
strcpy(pTmp2, this->front_strch(pSrc2,'-')+sizeof(char));
}
this->set_strch(pTmp1, pTmp2, '0');
strcpy(pSrc1, this->usign_sub(pTmp1,pTmp2));
}
TWO_DELETE(pTmp1, pTmp2);
CLS_STRCH(pSrc1);
return pSrc1;
}
// -=
Double& Double::operator -=(const Double& Obj)
{
int len=strlen(Obj.m_Src);
char *pObj=NULL;
NEW_SET(pObj,0,len+1);
strcpy(pObj,Obj.m_Src);

this->sign_sub_handle(this->m_Src, pObj);
DELETE(pObj);
return *this;
}
// -
Double& Double::operator -(const Double& Obj)
{
*this-=Obj;
return *this;
}
char* Double::usign_mul(char* pSrc1, char *pSrc2)
{
int i=0;
int j=0;
char flags=1;
int len=strlen(pSrc1);
char *pSum1=NULL;
char *pSum=NULL;

TWO_NEW_SET(pSum, pSum1, 0, 2*len+NEW_NUM);
TWO_REVERSE(pSrc1, pSrc2);
for (i=0; i<len; i++)
{
for (j=0; j<len; j++)
{
memset(pSum1, 0, 2*len+NEW_NUM);
memset(pSum1, '0', i+j);

*(pSum1+j+i)=(*(pSrc1+i)-'0')*(*(pSrc2+j)-'0');
if (*(pSum1+j+i)>9)
{
*(pSum1+j+i+1)+=*(pSum1+j+i)/10+'0';
*(pSum1+j+i)=*(pSum1+j+i)%10+'0';
}
else
{
*(pSum1+j+i)+='0';
}
this->reverse(pSum1);
this->usign_add(pSum, pSum1);
}
}
TWO_REVERSE(pSrc1, pSrc2);
strcpy(pSrc1, pSum);
TWO_DELETE(pSum, pSum1);
return pSrc1;
}
char* Double::sign_mul_handle(char* pSrc1, char* pSrc2)
{
char flags=0;
char *pTmp1=NULL;
char *pTmp2=NULL;
int len1=strlen(pSrc1);
int len2=strlen(pSrc2);

if (this->front_strch(pSrc1, '.')) pSrc1[len1-strlen(this->front_strch(pSrc1, '.'))]='\0';
if (this->front_strch(pSrc2, '.')) pSrc2[len2-strlen(this->front_strch(pSrc2, '.'))]='\0';
TWO_NEW_SET(pTmp1, pTmp2, 0, MAX(len1,len2)*2+NEW_NUM);
//正正或者负负
if ((NULL==this->front_strch(pSrc1,'-') && NULL==this->front_strch(pSrc2,'-')) || \
(this->front_strch(pSrc2, '-') && this->front_strch(pSrc2, '-')))
{
if(this->front_strch(pSrc1, '-') && this->front_strch(pSrc2, '-'))
{
strcpy(pTmp1, this->front_strch(pSrc1,'-')+1);
strcpy(pTmp2, this->front_strch(pSrc2,'-')+1);
}
else
{
strcpy(pTmp1, pSrc1);
strcpy(pTmp2, pSrc2);
}
}
else
{
flags=1;
if (this->front_strch(pSrc1, '-'))
{
strcpy(pTmp1, this->front_strch(pSrc1,'-')+1);
strcpy(pTmp2, pSrc2);
}
else
{
strcpy(pTmp1, pSrc1);
strcpy(pTmp2, this->front_strch(pSrc2,'-')+1);
}
}
this->set_strch(pTmp1, pTmp2, '0');
this->usign_mul(pTmp1, pTmp2);
if (flags) sprintf(pSrc1, "%c%s", '-', pTmp1);
else strcpy(pSrc1, pTmp1);
TWO_DELETE(pTmp1, pTmp2);
return pSrc1;
}
// *=
Double& Double::operator *=(const Double& Obj)
{
char *pObj=NULL; //pObj临时操作变量

NEW_SET(pObj, 0, Obj.size()+1);
strcpy(pObj,Obj.m_Src);
this->sign_mul_handle(this->m_Src, pObj);
DELETE(pObj);
return *this;
}
Double& Double::operator *(const Double& Obj)
{
*this*=Obj;
return *this;
}
// /=
Double& Double::operator /=(const Double& Obj)
{
return *this;
}
// /
Double& Double::operator /(const Double& Obj)
{
return *this;
}

int Double::operator >(const Double& Obj)
{
return this->compare(Obj)==1;
}

int Double::operator >=(const Double& Obj)
{
return this->compare(Obj)==1 || this->compare(Obj)==0;
}

int Double::operator <(const Double& Obj)
{
return this->compare(Obj)==-1;
}

int Double::operator <=(const Double& Obj)
{
return this->compare(Obj)==-1 || this->compare(Obj)==0;
}

int Double::operator ==(const Double& Obj)
{
return this->compare(Obj)==0;
}

int Double::compare(const Double& Obj)
{
int len1=strlen(this->m_Src);
int len2=strlen(Obj.m_Src);

if(len1>len2)
return 1;
else if(len1<len2)
return -1;
else
return strcmp(this->m_Src, Obj.m_Src);
}

int Double::compare(const Double& Obj1, const Double& Obj2)
{
return this->compare(Obj1, Obj2);
}