Смекни!
smekni.com

Манипулирование с целыми числами произвольной длины (стр. 2 из 2)

void

init0(), //init by zero

NotDigit(), //message "no digit" & init0

optimize(), //optimize length of body

error(char*); //display error message

};

inline int operator ==(unlim &a,unlim &b)

{

return !(a!=b);

}

inline int operator <=(unlim &a,unlim &b)

{

return (a<b) || !(a!=b);

}

inline int operator >=(unlim &a,unlim &b)

{

return !(a<b);

}

inline int operator >(unlim &a,unlim &b)

{

return !(a<b) && (a!=b);

}

inline unlim operator +(unlim &x)

{

return x;

}

programm3;

#include <stdlib.h>

#include <ctype.h>

#include <string.h>

#include <iostream.h>

#define COUNT unsigned int

#define TRUE 1

#define FALSE 0

#define ILLEGAL 10

enum

{

PLUS,

MINUS

};

class unlim

{

public:

unlim(char*);

unlim();

unlim(unlim&);

~unlim();

unlim

&operator = (char*),

&operator = (unlim&);

friend int

operator == (unlim&,unlim&),

operator != (unlim&,unlim&),

operator > (unlim&,unlim&),

operator >= (unlim&,unlim&),

operator < (unlim&,unlim&),

operator <= (unlim&,unlim&);

friend unlim

operator + (unlim&), // unary

operator - (unlim&), // unary

operator + (unlim&,unlim&), // binary

operator - (unlim&,unlim&), // binary

operator * (unlim&,unlim&),

abs(unlim&);

friend ostream

&operator << (ostream&,unlim&);

private:

struct descriptor

{

char

*body;

COUNT

len,

HowMany;

};

descriptor

*pv; //pointer to value descriptor

char

sign,

digit(COUNT number);

char &operator [](COUNT i) {return pv->body[i];}

void

init0(), //init by zero

NotDigit(), //message "no digit" & init0

optimize(), //optimize length of body

error(char*); //display error message

};

inline void unlim::error(char *message)

{

cout <<"Unlim class error: "

<<message

<<"&bsol;n";

}

void unlim::init0()

{

(pv->body)=new char;

*(pv->body)=0;

(pv->len)=1;

sign=PLUS;

}

char unlim::digit(COUNT number)

{

if ( number>=(pv->len) )

return ILLEGAL;

char byte=(pv->body)[number/2];

if (number%2==0)

return byte%10;

else

return byte/10;

}

unlim::unlim()

{

pv=new descriptor;

init0();

(pv->HowMany)=1;

}

unlim::~unlim()

{

if ( --(pv->HowMany)==0 )

{

delete pv->body;

delete pv;

}

}

char DecVal(char symbol)

{

if ( isdigit(symbol) )

return symbol-'0';

return ILLEGAL;

}

unlim::unlim(char *string)

{

pv=new descriptor;

(pv->HowMany)=1;

COUNT Length=strlen(string);

if (Length==0)

{

error("Empty string assigned. Value=0");

init0();

return;

}

else

{

COUNT LeftLimit=0;

switch (string[0])

{

case '-':

sign=MINUS;

LeftLimit=1;

break;

case '+':

LeftLimit=1;

default:

sign=PLUS;

}

if (Length-LeftLimit==0)

{

error("Sign without value. Value=0");

init0();

return;

}

else

{

while (string[LeftLimit]=='0')

LeftLimit++;

if ( (Length-=LeftLimit)==0 )

{

init0();

return;

}

COUNT DestLength=Length/2+Length%2;

(pv->body)=new char[DestLength];

for ( COUNT si=Length+LeftLimit-1, ki=0 ; ki<DestLength ; si-=2,ki++ )

{

char a=DecVal(string[si]);

if (a==ILLEGAL)

{

NotDigit();

return;

}

(pv->body)[ki]=a;

if (si!=LeftLimit)

{

char a=DecVal(string[si-1]);

if (a==ILLEGAL)

{

NotDigit();

return;

}

(pv->body)[ki]+=10*a;

}

}

(pv->len)=Length;

}

}

}

void unlim::NotDigit()

{

error("Not digit symbol in string. String ignored. Value=0");

delete pv->body;

init0();

}

unlim::unlim(unlim &arg)

{

(arg.pv)->HowMany++;

pv=arg.pv;

sign=arg.sign;

}

unlim &unlim::operator=(unlim &arg)

{

(arg.pv)->HowMany++;

if ( --(pv->HowMany)==0 )

{

delete pv->body;

delete pv;

}

pv=arg.pv;

sign=arg.sign;

return *this;

}

unlim &unlim::operator=(char *string)

{

return *this=unlim(string);

}

ostream &operator<<(ostream &s,unlim &x)

{

if (x.sign==MINUS)

s << "-";

for ( COUNT i=((x.pv)->len) ; i>0 ; i-- )

s << int(x.digit(i-1));

return s;

}

int operator!=(unlim &a,unlim &b)

{

if ( (a.pv)->len != (b.pv)->len)

return TRUE;

if (a.sign!=b.sign)

return TRUE;

COUNT length=((a.pv)->len)/2+((a.pv)->len)%2;

for ( COUNT i=0 ; i<length ; i++ )

if (a[i]!=b[i])

return TRUE;

return FALSE;

}

int operator<(unlim &a,unlim &b)

{

if (a.sign!=b.sign)

return a.sign==MINUS;

if ( (a.pv)->len == (b.pv)->len )

{

COUNT i=((a.pv)->len)-1;

while ( a.digit(i) == b.digit(i) )

{

if (i==0)

return FALSE;

i--;

}

char

aLess= a.digit(i) < b.digit(i),

SignPlus= a.sign==PLUS;

return ( aLess && SignPlus) || ( !aLess && !SignPlus );

}

else

{

char

aShort= (a.pv)->len < (b.pv)->len,

SignPlus= a.sign==PLUS;

return ( aShort && SignPlus ) || ( !aShort && !SignPlus );

}

}

inline int operator ==(unlim &a,unlim &b)

{

return !(a!=b);

}

inline int operator <=(unlim &a,unlim &b)

{

return (a<b) || !(a!=b);

}

inline int operator >=(unlim &a,unlim &b)

{

return !(a<b);

}

inline int operator >(unlim &a,unlim &b)

{

return !(a<b) && (a!=b);

}

inline unlim operator +(unlim &x)

{

return x;

}

unlim abs(unlim &x)

{

unlim r=x;

r.sign=PLUS;

return r;

}

unlim operator -(unlim &x)

{

if ( (x.pv)->len==1 && x[0]==0 )

{

unlim y;

return y;

}

unlim y=x;

if (x.sign==PLUS)

y.sign=MINUS;

else

y.sign=PLUS;

return y;

}

void unlim::optimize()

{

COUNT i=pv->len/2+pv->len%2-1;

char optimized=FALSE;

while (pv->body[i]==0)

{

optimized=TRUE;

if (i--==0)

{

init0();

return;

}

}

if (optimized)

{

char *NewBody=new char[++i];

for (COUNT ni=0;ni<i;ni++)

NewBody[ni]=pv->body[ni];

delete pv->body;

pv->body=NewBody;

pv->len=(i--)*2;

}

if ( (pv->body[i]/10)==0 && (pv->len%2)==0 )

pv->len--;

}

inline COUNT max (COUNT a,COUNT b)

{

return (a>b)?a:b;

}

unlim operator +(unlim &a,unlim &b)

{

unlim r;

delete (r.pv)->body;

if (a.sign==b.sign)

{

r.sign=a.sign;

COUNT

rlen=max( (a.pv)->len,(b.pv)->len )+1,

alen=(a.pv)->len/2+(a.pv)->len%2,

blen=(b.pv)->len/2+(b.pv)->len%2;

(r.pv)->len=rlen;

rlen=rlen/2+rlen%2;

(r.pv)->body=new char[rlen];

*(r.pv)->body=0;

for (COUNT i=0;i<rlen;i++)

{

unsigned char sum=( i<alen ? a[i] : 0)+( i<blen ? b[i] : 0);

r[i]+=sum%100;

r[i+1]=sum/100;

}

if ( r.digit( (r.pv)->len-1 )==0 )

(r.pv)->len--;

}

else

{

unlim

aa=a,

bb=b;

if (abs(a)<abs(b))

{

aa=b;

bb=a;

}

r.sign=aa.sign;

COUNT

rlen=(aa.pv)->len,

blen=(bb.pv)->len/2+(bb.pv)->len%2;

(r.pv)->len=rlen;

rlen=rlen/2+rlen%2;

(r.pv)->body=new char[rlen];

*(r.pv)->body=0;

for (COUNT i=0;i<rlen;i++)

{

char sub=aa[i]-( i<blen ? bb[i] : 0 )+r[i];

if (sub<0)

{

r[i+1]=-1;

sub+=100;

}

else

r[i+1]=0;

r[i]=sub;

}

r.optimize();

}

return r;

}

unlim operator -(unlim &a,unlim &b)

{

return a+(-b);

}

unlim operator *(unlim &a,unlim &b)

{

unlim r;

delete (r.pv)->body;

if (a.sign==b.sign)

r.sign=PLUS;

else

r.sign=MINUS;

COUNT

rlen=(a.pv)->len+(b.pv)->len,

alen=(a.pv)->len/2+(a.pv)->len%2,

blen=(b.pv)->len/2+(b.pv)->len%2;

(r.pv)->len=rlen;

rlen=rlen/2+rlen%2;

(r.pv)->body=new char[rlen];

COUNT i;

for (i=0;i<rlen;i++)

r[i]=0;

for (i=0;i<alen;i++)

{

unsigned int

next=0,

mul;

for(COUNT j=0;j<blen;j++)

{

next+=r[i+j];

mul=a[i]*b[j]+next;

r[i+j]=mul%100;

next=mul/100;

}

r[i+blen]=next;

}

if ( r.digit((r.pv)->len-1)==0 )

(r.pv)->len--;

if ( r.digit((r.pv)->len-1)==0 )

r.init0();

return r;

}