- •1. Objectives of the Term Work
- •2. Basic Principles
- •2.1. Digital Logarithmic (dl) Representation
- •0(Zero)
- •Integer part Fractional part
- •2.2. Basic Rules of dl Arithmetic
- •2.3. Basic Algorithms of Data Processing
- •3. Models of Data Structures in the Main Memory
- •Figure 4.1 Class Diagram
- •5. Solution of the task of term assignment
- •Figure 5.1. Snapshot of result.
- •4. Processing the dl-type of Data in computer
- •Attachment. Source code of the developed class.
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 ")
{
//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
ГАМАЮН В. П. Моделювання багаторозрядних комп’ютерних систем: Навч. посібник. – К.: Книжкове вид-во НАУ, 2007. – 112 с.
ГАМАЮН В. П. Разрядно-логарифмическая арифметика. Методы и алгоритмы. К.: – Книжное изд-во НАУ, 2007. – 272 с.
Бронштейн И. Н., Семендяев К. А. Справочник по математике для инженеров и студентов вузов. – М.: Наука ,1986. – 544 с.
Демидович Б. П., Марон И. А. Основы вычислительной математики. – М.: Наука, 1970. – 664 с.
СТРАУСТРУП Б. Программирование на С++. –М.: Мир, 1998. -1226 с.
