Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CMS_term_Andrushchenko.doc
Скачиваний:
1
Добавлен:
01.05.2025
Размер:
370 Кб
Скачать
☆

Attachment. Source code of the developed class.

#include <math.h>

const int limit =66;

const int max =66;

const int Q=64; //number of bits in the DL word

class A1

{

public:

double x, chis;

int Reg [Q+2] ;

int NUM;

A1();

A1(double x);

A1( int);

A1(const A1 &R);

~A1();

A1& operator = (double); //assignment operator

A1& operator = (A1 x); //overloaded assignment operator

A1 operator+(A1 &x);// reloading the operator of summation A1+A1;

A1 operator*(A1 &x);//reloading operator of multiplication

A1 operator-(A1 &x);//reloading operator of subtraction

A1 operator/(A1 &x);//reloading the division operator

void ToString(char* buf);//returns the string containing the decimal representation of current DL word

private:

void PRV (double); // converts the double number into the DL code

void Sub (A1 OP1,A1 OP2,A1 &RS);// minuend,subtrahend,result/

bool Rest(A1 OP1,A1 OP2,A1& rest);//returns the remainder of division OP1 by OP2, returns false if division by zero

void Sum (A1 OP1,A1 OP2,A1& RS); //first term bits,second term bits,result term bits.

void ToArray(int Res[]);

void SortArray();

void FromArray(int Arr[]);

static void SortArray(int Res[]);

static void CollectTerms(int Res[]);

void Mul(A1 term1, A1 term2, A1& prod);//multiplication

bool Div(A1 term1, A1 term2, A1& quot);//division

bool Mod(A1 OP1,A1 OP2);//decides which of arguments is bigger

bool IsEqual(A1 OP1,A1 OP2);//returns true if OP1 is equal to OP2

int Contained(int Res[],int key);//function searches for specified element "key" in given array

void Exclude(int Res[],int pos);//excludes element with position "pos" from given array

};

#include "DLClass.h"

A1::A1()

{

//standart constructor

chis=0;

Reg[0]=0;Reg[1]=0; //the sign is set "+", number of significant bits=0

}

A1::A1(double x)

{

//overloaded constructor with double input value

PRV(x); //converts x into DL

}

A1::A1(int val)

{

//overloaded constructor with input integer value;

double x=(double)val;

PRV(x);

}

A1::~A1()

{

//destructor

//should clear the memory here

}

A1::A1(const A1 &R) // copy construct

{

int i;

Reg[Q]=R.Reg[Q]; // work with objects only after their creation

for(i=0;i<=Q+1;i++)

Reg[i]=R.Reg[i];

}

A1 A1 :: operator+(A1 &x)

{

//overloaded addition operator over class objects

A1 rez;

A1 A=*this;

if((A.Reg[0]==0)&&(x.Reg[0]==0))

{

//both are positive

Sum(*this,x,rez);

}

else if((A.Reg[0]==1)&&(x.Reg[0]==1))

{

//both are negative

Sum(*this,x,rez);

rez.Reg[0]=1;

}

else

{

if(A.Reg[0]==1)

Sub(x,A,rez);

else

Sub(A,x,rez);

}

return rez;

}

A1 A1::operator -(A1 &x)

{

A1 rez;

A1 A=*this;

if((A.Reg[0]==0)&&(x.Reg[0]==0))

{

//both are positive

Sub(*this,x,rez);

}

else if((A.Reg[0]==1)&&(x.Reg[0]==1))

{

//both are negative

Sub(x,*this,rez);

rez.Reg[0]=!rez.Reg[0];

}

else

{

//-+

if(A.Reg[0]==1)

{

Sum(x,A,rez);

rez.Reg[0]=!rez.Reg[0];

}

else//+-

{

Sum(A,x,rez);

}

}

return rez;

}

A1 A1::operator /(A1 &x)

{

A1 rez;

bool res=Div(*this,x,rez);

if(!res)

{

//division by zero

return *this;

}

return rez;

}

A1 A1::operator *(A1 &x)

{

A1 rez;

Mul(*this,x,rez);

return rez;

}

void A1 :: PRV(double x)

{

//function must convert the double value into DL object

int k = limit;

int z= 0;

double f, r;//f - absolute value of x

//set the sign of DL number

if(x < 0)

{

Reg[0] = 1;

}

else

{

Reg[0] = 0;

}

f = fabs(x);//get the absolute value

if(f == 0)

{

//if the value is zero

Reg[0] = 0;

Reg[1] = 0;

return;

}

do{

r = f - pow(2.0, k);

if(r < 0)

{

k--;

continue;

}

else if(r > 0)

{

Reg[2+z] = k;

z++;

Reg[1] = z;

f = r;

}

else

{

Reg[2+z] = k;

z++;

Reg[1] = z;

return;

}

}

while(k > -1*limit);

return;

}

A1&A1 ::operator = (double x) // assignment operator

{

int i; int RReg[Q];

PRV(x);

for (i=0;i<=Reg[1]+1;i++) {RReg[i]=Reg[i];}

return *this;

}

A1&A1 ::operator = ( A1 x) // assignment RL=RL

{

int i;

Reg[Q]=x.Reg[Q]; // work with objects only after their creation

for (i=0; i<=x.Reg[1]+1;i++ ) {Reg[i]=x.Reg[i];}

return*this;

}

void A1:: Sum (A1 OP1,A1 OP2,A1& RS)// summing

{

//int* Reg=new int [max*2]; int*Reg1=new int[max]; // work with objects only after their creation

static int Reg[max*2];

if((OP1.Reg[1]==0)&&(OP2.Reg[1]==0))

{

//both numbers equal to zero

RS=0;

}

else if((OP1.Reg[1]==0)||(OP2.Reg[1]==0))

{

//one of operands equals to zero

if(OP1.Reg[1]==0)

{

RS=OP2;

}

else

{

RS=OP1;

}

}

else

{

//operands are non zeros

//let's collect sum in the Reg array

OP1.ToArray(Reg); //write to result operand1

Reg[1]=OP1.Reg[1]+OP2.Reg[1];//set the length

for(int i=2;i<OP2.Reg[1]+2;i++)

{

Reg[i+OP1.Reg[1]]=OP2.Reg[i];

}

//now both operands are stored in Reg[]

//we should sort and collect terms in it

SortArray(Reg);

CollectTerms(Reg);

//now the sum is stored in Reg[]

//time to fill in the RS object

RS.FromArray(Reg);

}

//return RS[Q];

//delete Reg;

// delete []Reg1;

}

void A1::ToArray(int Res[])

{

int i;

Res[Q]=this->Reg[Q]; // work with objects only after their creation

for (i=0; i<=this->Reg[1]+1;i++ )

{

Res[i]=this->Reg[i];

}

}

void A1::SortArray()

{

char is=1;

int i;

int c;

while(is)

{

is=0;

for (i=3; i<=(Reg[1]+1); i++)

if ( Reg[i] > Reg[i-1] )

{

c=Reg[i];

Reg[i]=Reg[i-1];

Reg[i-1]=c;

is=1;

}

}

}

void A1::SortArray(int Res[])

{

char is=1;

int i;

int c;

while(is)

{

is=0;

for (i=3; i<=(Res[1]+1); i++)

if ( Res[i] > Res[i-1] )

{

c=Res[i];

Res[i]=Res[i-1];

Res[i-1]=c;

is=1;

}

}

}

void A1::CollectTerms(int Res[])

{

int i=0; //iterator

int length=Res[1]+1;

int n=0;

i=length;

while(i>2)

{

if(Res[i]==Res[i-1])

{

//terms are equal

Res[i-1]++;

Res[i]=-13278;

length--;

i=length;

SortArray(Res);

}

else

{

//go next i

i--;

}

}

SortArray(Res);

Res[1]=length-1;

}

void A1::FromArray(int Arr[])

{

int n=0;

int limit;

if(Arr[1]>Q)

limit=max;

else

limit=Arr[1]+2;

for(int i=0;i<limit;i++)

{

this->Reg[i]=Arr[i];

n++;

}

this->Reg[1]=n-2;

}

void A1::Mul(A1 term1,A1 term2,A1 &prod)

{

int* Reg=new int [4356];//переписать под массив

Reg[0] = term1.Reg[0] ^ term2.Reg[0];//set the sign of product

int l = 0;

for(int i=2;i<=term1.Reg[1]+1;i++)

for (int j = 2; j <= term2.Reg[1] + 1; j++)

{

l++;

Reg[l + 1] = term1.Reg[i] + term2.Reg[j];

}

Reg[1] = l;

SortArray(Reg);

CollectTerms(Reg);

prod.FromArray(Reg);

delete[] Reg;

}

void A1::Sub (A1 OP1,A1 OP2,A1 &RS)

{

//function that subtracts OP2 from OP1 and returns the result in RS

int *Ar=new int[max*2];

int *Br=new int[max*2];

int *B1 = new int[max*max];

bool MinuendIsGreater=false;

int ArMost;//the most significant digit of minuend

int BrLeast;//the least significant digit of subtrahend

int ArLeast;//the least significant digit of minuend

int n = 0;

//by default the result is zero

RS.Reg[0]=0;

RS.Reg[1]=0;

//check if minuend or subtrahand aren't equal and are not zero

if(!IsEqual(OP1,OP2))

if((OP1.Reg[1]==0)||(OP2.Reg[1]==0))

{

//either minuent or subtrahand are zero

if((OP1.Reg[1]==0)&&(OP2.Reg[1]==0))

{

//both are equal zero

RS.Reg[0]=0;

RS.Reg[1]=0;

}

else if(OP1.Reg[1]==0)

{

//minuend is equal to zero

RS=OP2;

RS.Reg[0]=1;

}

else

{

//subtrahend is equal to zero

RS=OP1;

}

}

else

{

//minuend and subtrahend are non zero

MinuendIsGreater=Mod(OP1,OP2);

if(MinuendIsGreater)

{

OP1.ToArray(Ar);

OP2.ToArray(Br);

}

else

{

OP2.ToArray(Ar);

OP1.ToArray(Br);

}

//Ar is minuend

//Br is subtrahend

//B1 would be complementary code result

//now we can exclude from both arrays the same bits

int j=0;//aux

int k=0;//aux

for(int i=Ar[2];i>=Ar[Ar[1]+1];i--)

{

j=Contained(Ar,i);

k=Contained(Br,i);

if(j&&k)

{

Exclude(Ar,j);

Exclude(Br,k);

}

}

//some of operands may become zero

if(Ar[1]==0||Br[1]==0)

{

if(Ar[1]==0&&Br[1]==0)

{

RS.Reg[0]=0;

RS.Reg[1]=0;

}

else

if(Ar[1]==0)

{

RS.FromArray(Br);

}

else if(Br[1]==0)

RS.FromArray(Ar);

}

else

{

ArMost=Ar[2];

ArMost--; //should be decreased by 1

BrLeast=Br[Br[1]+1];

ArLeast=Ar[Ar[1]+1];

//now we exclude the most significant digit from the minuend

for (int i = 2; i <=Ar[1] + 1; i++)

{

Ar[i] = Ar[i + 1];

}

Ar[1]--;

//now the complement code should be formed

int n=2;//auxilliary counter

int index=-1;

if(BrLeast<index)index=BrLeast;

if(ArLeast<index)index=ArLeast;

for (int i=ArMost;i>index;i--)

{

B1[n]=i;

n++;

}

B1[1]=n-2;

//now should exclude the bits that are common for B1 and Br

for(int i=2;i<=Br[1]+1;i++)

{

if(n=Contained(B1,Br[i]))

Exclude(B1,n);

}

//bits are excluded next step is to add Ar to B1

SortArray(Ar);

SortArray(B1);

OP1.FromArray(Ar);

OP2.FromArray(B1);

OP2.Reg[0]=0;

Sum(OP1,OP2,RS);

//finally add the least significant digit to result

index=RS.Reg[1]+2;

if(index<max)

{

if(BrLeast<0)

RS.Reg[index]=BrLeast;

else

RS.Reg[index]=0;

RS.Reg[1]++;

RS.CollectTerms(RS.Reg);

}

}

if(!MinuendIsGreater)

RS.Reg[0]=1;

}

delete[] Ar;

delete[] Br;

delete[] B1;

}

bool A1::Mod(A1 OP1,A1 OP2)

{

//this function compares OP1 and OP2 by modulus

//if OP1>OP2 return true, otherwise returns false

for(int i=2;i<=OP1.Reg[1]+1;i++)

{

if(OP1.Reg[i]<OP2.Reg[i])

{

return false;

}

if(OP1.Reg[i]>OP2.Reg[i]||i==OP2.Reg[1]+1)

{

return true;

}

}

return false;

}

int A1::Contained(int Res[],int key)

{

for(int i=2;i<=Res[1]+1;i++)

if(Res[i]==key)return i;

return 0;

}

void A1::Exclude(int Res[],int pos)

{

if(pos==Res[1]+1)

{

Res[1]--;

return;

}

for(int i=pos;i<Res[1]+1;i++)

{

Res[i]=Res[i+1];

}

Res[1]--;

}

bool A1::Div(A1 term1,A1 term2,A1 &quot)

{

//function performs division quot=term1/term2;

//result is set to quot;

//if division by zero occurs, nothing is set to quot and false returned;

//otherwise true is returned

//firstly check for operands to be zeros

if(term1.Reg[1]==0)

{

//divided is equal to zero

quot.Reg[0]=0;

quot.Reg[1]=0;

return true;

}

if(term2.Reg[1]==0)

{

//divisor is equal to zero

return false;

}

//neither divided nor divisor is equal to zero

//must perform division

int* A=new int[max*2];//divided

int* B =new int[max*2];//divisor

int* C=new int[max*2];//quotient

/*int* E=new int[max*2];//auxilliary

int* F=new int[max*2];//auxilliary

int* G=new int[max*2];//auxilliary

*/

A1 E;//aux

A1 F;//aux

A1 G;//aux

term1.ToArray(A);

term2.ToArray(B);

//now set the sign of the quotient

C[0]=A[0]^B[0];

//set the positive signs

A[0]=0;

B[0]=0;

E.Reg[0]=0;

//begin division

E.Reg[1]=1;

int i=A[2]-B[2];

C[1]=0;

while(C[1]<Q)

{

E.Reg[2]=i;

term2.FromArray(B);

Mul(E,term2,F);

term1.FromArray(A);

Sub(term1,F,G);

if(G.Reg[1]==0)

{

//division is complete

C[C[1]+2]=i;

C[1]++;

break;

}

else

{

if(G.Reg[0]==0)

{

C[C[1]+2]=i;

C[1]++;

for (int j = 0; j <= G.Reg[1] + 1; j++)

{

A[j]=G.Reg[j];

}

}

i--;

}

}

quot.FromArray(C);

//do not forget to free the memory

delete[] A;

delete[] B;

delete[] C;

//delete[] E;

//delete[] F;

//delete[] G;

return true;

}

bool A1::IsEqual(A1 OP1,A1 OP2)

{

//returns true if equality is prooved

int length=OP1.Reg[1]+1;

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

{

if(OP1.Reg[i]!=OP2.Reg[i])

return false;

}

return true;

}

bool A1::Rest(A1 OP1,A1 OP2,A1& rest)

{

//function performs division OP1/OP2;

//remainder is set to rest;

//if division by zero occurs, nothing is set to rest and false returned;

//otherwise true is returned

//firstly check for operands to be zeros

if(OP1.Reg[1]==0)

{

//divided is equal to zero

rest.Reg[0]=0;

rest.Reg[1]=0;

return true;

}

if(OP2.Reg[1]==0)

{

//divisor is equal to zero

return false;

}

//neither divided nor divisor is equal to zero

//must perform division

int* A=new int[max*2];//divided

int* B =new int[max*2];//divisor

int* C=new int[max*2];//quotient

/*int* E=new int[max*2];//auxilliary

int* F=new int[max*2];//auxilliary

int* G=new int[max*2];//auxilliary

*/

A1 E;//aux

A1 F;//aux

A1 G;//aux

A1 H;//aux

OP1.ToArray(A);

OP2.ToArray(B);

//now set the sign of the quotient

C[0]=A[0]^B[0];

//set the positive signs

A[0]=0;

B[0]=0;

E.Reg[0]=0;

//begin division

E.Reg[1]=1;

int i=A[2]-B[2];

C[1]=0;

while(C[1]<Q&&i>=0)

{

E.Reg[2]=i;

H.FromArray(B);

Mul(E,H,F);

H.FromArray(A);

Sub(H,F,G);

if(G.Reg[1]==0)

{

//division is complete

C[C[1]+2]=i;

C[1]++;

break;

}

else

{

if(G.Reg[0]==0)

{

C[C[1]+2]=i;

C[1]++;

for (int j = 0; j <= G.Reg[1] + 1; j++)

{

A[j]=G.Reg[j];

}

}

i--;

}

}

//now C has got the quotient;

E.FromArray(C);

Mul(E,OP2,F);//multiply quotient by divisor

Sub(OP1,F,rest);//get remainder

//do not forget to free the memory

delete[] A;

delete[] B;

delete[] C;

//delete[] E;

//delete[] F;

//delete[] G;

return true;

}

void A1::ToString(char* buf)

{

//the weight coeficient would be 100

A1 K=1000000000000000000.0;//divider

A1 quot; //the quotient of division

A1 rest; //the rest of division

A1 A;//the given value

A1 aux=100;//we divide our divider by this value at each step

A1 aux1=99;//we compare our divider to this number to know if we finished

A1 fraction=*this;//the fractional part of given number

int i;//counter

int res;//2 digits of temporary result are stored here

bool grThanZero=false;

A1 int_part;//integral part of quotient

//BEGIN WITH INTEGRAL PART

char number[256];//here the string with decimal representation is placed, must return it when functionality

//is prooved

SecureZeroMemory(number,256);

char tmp[16];//temporary string

A=*this;//the number to be converted into string

//we must eliminate the fractional part

for(int i=2;i<=A.Reg[1]+1;i++)

{

if(A.Reg[i]<0)

{

A.Reg[1]=i-2;

break;

}

}

while(Mod(K,aux1))

{

quot=A/K;

Rest(A,K,rest);

i=0;

if(quot.Reg[1]>0)

while(quot.Reg[i]>=0)

{

int_part.Reg[i]=quot.Reg[i];

i++;

}

int_part.Reg[1]=i-2;

res=0;

//convert the integr_part into double

if(i>2)

{

for(int i=2;i<=int_part.Reg[1]+1;i++)

{

res+=(int)pow(2.0,int_part.Reg[i]);

}

}

//res contains the 2 digits of result

if(res!=0)

{

_itoa_s(res,tmp,16,10);

if(strlen(tmp)<2)

{

tmp[1]=tmp[0];

tmp[0]='0';

tmp[2]=0;

}

}

else

{

strcpy_s(tmp,16,"00");

}

strcat_s(number,25,tmp);

A=rest;

K=K/aux;

}

//the last rest also gives us some digits

res=0;

for(int i=2;i<=A.Reg[1]+1;i++)

{

res+=(int)pow(2.0,A.Reg[i]);

}

if(res!=0)

{

_itoa_s(res,tmp,16,10);

if(strlen(tmp)<2)

{

tmp[1]=tmp[0];

tmp[0]='0';

tmp[2]=0;

}

}

else

{

strcpy_s(tmp,16,"00");

}

strcat_s(number,256,tmp);

strcat_s(number,256,".");

//at this moment the integral part should be formed, as it is.

//now should take care about the fractional part

//we clear all the integer bits from number

for(int i=2;i<=fraction.Reg[1]+1;i++)

{

if(fraction.Reg[i]>=0)

{

Exclude(fraction.Reg,i);

i=1;

}

}

//now we obtain fraction

while(fraction.Reg[1]>0&&strlen(number)<256)

{

//if non empty fraction

A=fraction*aux;

//int_part of A is to be converted

res=0;

for(int i=2;i<=A.Reg[1]+1;i++)

{

if(A.Reg[i]<0)

break;

res+=(int)pow(2.0,A.Reg[i]);

}

if(res!=0)

{

_itoa_s(res,tmp,16,10);

if(strlen(tmp)<2)

{

tmp[1]=tmp[0];

tmp[0]='0';

tmp[2]=0;

}

}

else

{

strcpy_s(tmp,16,"00");

}

strcat_s(number,256,tmp);

//prepare to next iteration

for(int i=2;i<=A.Reg[1]+1;i++)

{

if(A.Reg[i]>=0)

{

Exclude(A.Reg,i);

i=1;

}

}

fraction=A;

}

//finally we should tream all zeros

char* ptr; //pointer to not-zero in number string

ptr=number;

while(*++ptr=='0');

//set sign;

if(A.Reg[0]==0)

strcpy_s(buf,256,"+");

else

strcpy_s(buf,256,"-");

strcat_s(buf,256,ptr);

}

BIBLIOGRAPHY

  1. ГАМАЮН В. П. Моделювання багаторозрядних комп’ютерних систем: Навч. посібник. – К.: Книжкове вид-во НАУ, 2007. – 112 с.

  2. ГАМАЮН В. П. Разрядно-логарифмическая арифметика. Методы и алгоритмы. К.: – Книжное изд-во НАУ, 2007. – 272 с.

  3. Бронштейн И. Н., Семендяев К. А. Справочник по математике для инженеров и студентов вузов. – М.: Наука ,1986. – 544 с.

  4. Демидович Б. П., Марон И. А. Основы вычислительной математики. – М.: Наука, 1970. – 664 с.

  5. СТРАУСТРУП Б. Программирование на С++. –М.: Мир, 1998. -1226 с.

28

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]