#include <iostream>
#include "bignum.h"
//#include <algorithm>
using namespace std;
int main() {
try {
// BigNum a;
// std::cout<<'\n'<<std::string(50,'_')<<endl;
BigNum a("5"),b("4"),c("-5"),d("-4");
// BigNum a=5,b=4,c=-5,d=-4;
// BigNum is_ambiguous=std::string('4'); //konstruktor kopcujący
// BigNum is_ambiguous="5"; // konstruktor kopcujący
// a=std::string("5");b=std::string("4");c=std::string("-5");d=std::string("-4");
// a="5";b="4";c="-5";d="-4";
o(b+c)
std::cout<<'\n'<<std::string(50,'_')<<endl;
// BigNum d("7891");
// std::cout<<'\n'<<std::string(50,'_')<<endl;
// BigNum e("1111");
// std::cout<<'\n'<<std::string(50,'_')<<endl;
// BigNum f("1111");
// std::cout<<'\n'<<std::string(50,'_')<<endl;
// BigNum d("4-567");
// std::cout<<'\n'<<std::string(50,'_')<<endl;
// cout<<"b+c="<<b+c<<endl; ///4�912
// std::cout<<'\n'<<std::string(50,'_')<<endl;
// o(d+c) ///12�458
// std::cout<<'\n'<<std::string(50,'_')<<endl;
// o(e+f)
// std::cout<<'\n'<<std::string(50,'_')<<endl;
// o(e+c)
// BigNum z("");
std::cout<<'\n'<<std::string(50,'*')<<endl;
o(BigNum("-5")+BigNum("4"))
o(BigNum("5")+BigNum("4"))
o(BigNum("-5")+BigNum("-4"))
o(BigNum("5")+BigNum("-4"))
std::cout<<'\n'<<std::string(50,'*')<<endl;
o(BigNum("-4")+BigNum("4"))
o(BigNum("4")+BigNum("4"))
o(BigNum("-4")+BigNum("-4"))
o(BigNum("4")+BigNum("-4"))
std::cout<<'\n'<<std::string(50,'*')<<endl;
o(BigNum("-4")+BigNum("5"))
o(BigNum("4")+BigNum("5"))
o(BigNum("-4")+BigNum("-5"))
o(BigNum("4")+BigNum("-5"))
std::cout<<'\n'<<std::string(50,'_')<<endl;
//
// BigNum g=b-c;
// o(g);
// g.print();
// (g-c).print();
// g=g-c;
// o(g)
// g.print();
// o(b-c);// błąd przekroczenie tablicy
o((BigNum(std::string(2,'2'))+BigNum(std::string(2,'3'))))
//o(b+c)
}
catch(std::exception & e) {
std::cerr<<e.what()<<std::endl;
exit(-1);
} catch(ERROR & e) {
std::cerr<<e.what()<<std::endl;
exit(-2);
} catch(...) {
exit(-3);
std::cerr<<"\nNieznany błąd"<<std::endl;
}
return 0;
}
#include "bignum.h"
BigNum::BigNum(const std::string& longNum):size{longNum.size()} {
switch(longNum.find('-')) {
case 0:
sign='-';
size--;
break;
case static_cast<size_t>(-1): // static_cast<size_t>(-1) - max int size_t, znaleziono na pozycji ostatniej czyli żadnej
break;
default:
correct = false;
throw WrongNum();
break;
}
if(longNum.size())
ptrLgNr=new char[size+1];
else // jeżeli zerowa długość rzuć wyjątkiem
throw ErrDim();
if(ptrLgNr)
for(auto it=longNum.cbegin(), end=longNum.cend(),last=end-1; it!=end; it++) {
switch(*it) {
case '0' ... '9':
ptrLgNr[last-it]=*it-'0';
break;
case '-':
ptrLgNr[last-it]=*it;
break;
case 0:
ptrLgNr[last-it]=*it;
break;
default:
correct=false;
throw WrongNum();
break;
}
}
}
BigNum::BigNum(const BigNum & other) { /*:size{other.size}*/
if(other.size) {
ptrLgNr=new char[other.size+1] {};
size=other.size;
for(size_t i; i<size ; i++) {
ptrLgNr[i]=other.ptrLgNr[i];
}
// memcpy(ptrLgNr,other.ptrLgNr,other.size);
} else
throw ErrDim();
}
BigNum::BigNum(const int& num){
*this=BigNum(std::to_string(num));
}
//BigNum::BigNum(std::string num){
// *this=BigNum(std::string(num));
//}
//BigNum::BigNum(const char& num){
// *this=BigNum(std::string(num,num+sizeof(num)));
//}
BigNum::~BigNum() {
if(ptrLgNr)
delete[]ptrLgNr;
}
BigNum& BigNum::operator=(const BigNum& rhs) {
if(this == &rhs)
return *this; // handle self assignment
delete [] ptrLgNr;
ptrLgNr=new char[rhs.size+1] {};
size=rhs.size;
for(size_t i; i<size ; i++) {
ptrLgNr[i]=rhs.ptrLgNr[i];
}
// std::copy(rhs.ptrLgNr,rhs.ptrLgNr+size,ptrLgNr); // wywalaja się makra o i po dołączeniu <algorithm>
//std::memcpy(rhs.ptrLgNr,ptrLgNr,size); //tylko dla typów wbudowanych ale i tak coś jest nie tak
return *this;
}
BigNum& BigNum::operator=(const int& num) {
*this=BigNum(std::to_string(num));
return *this;
}
BigNum& BigNum::operator=(std::string num) {
*this=BigNum(num);
return *this;
}
BigNum& BigNum::operator=(const char & num) {
*this=BigNum(std::string(num,num+sizeof(num)));
return *this;
}
BigNum operator + (const BigNum& lhs,const BigNum& rhs) {
BigNum temp(std::string(std::max(lhs.size,rhs.size)+1,'0')); // +1 znak '\0' kończący znak char.
int flag = 0b00;
if(rhs.sign=='+')
flag|=2;
if(lhs.sign=='+')
flag|=1;
if(temp.graterAbs(lhs,rhs)) //np |-5|>|4|=true
switch(flag) {
case 0:
// -5+(-4)= -(5+4)=
temp.sign='-';
temp.add(lhs,rhs);
break;
case 1:// o przeciwnych znakach
//5+(-4)= 5-4=1
temp.subtract(lhs,rhs);
break;
case 2:// o przeciwnych znakach
//-5+4= -5+4=-1
temp.sign='-';
temp.subtract(lhs,rhs);
break;
case 3:// obie dodatnie
//5+4= 5+4=9;
temp.add(lhs,rhs);
break;
default:
throw;
} else //np |-4|>|5|=false //zmieniona kolejność parametrów funkcji z (lhs,rhs) na (rhs,lhs)
switch(flag) {
case 0:// obie ujemne
// -4+(-5)= -(4+5)=-(5+4)=-9
temp.sign='-';
temp.add(rhs,lhs);
break;
case 1:// o przeciwnych znakach
//4+(-5)= 4-5=-(5-4)=-1
temp.sign='-';
temp.subtract(rhs,lhs); //zmieniona kolejność parametrów funkcji
break;
case 2:// o przeciwnych znakach
//-4+5= 5-4=1
temp.subtract(rhs,lhs);//zmieniona kolejność parametrów funkcji
break;
case 3:// obie dodatnie
//4+5= 5+4=9;
temp.add(rhs,lhs);//zmieniona kolejność parametrów funkcji
break;
default:
throw;
}
return temp;
}
BigNum operator - (const BigNum& lhs,const BigNum& rhs) {
BigNum temp(std::string(std::max(lhs.size,rhs.size)+1,'0')); // +1 znak '\0' kończący znak char.
int flag = 0b00;
if(rhs.sign=='+')
flag|=2;
if(lhs.sign=='+')
flag|=1;
// o(bitset<4>(flag))
if(temp.graterAbs(lhs,rhs)) //np |-5|>|4|=true
switch(flag) {
case 0:
// -5-(-4)= -(5-4)=-1
temp.sign='-';
temp.subtract(lhs,rhs);
break;
case 1:// o przeciwnych znakach
//5-(-4)= 5+4=9
temp.add(lhs,rhs);
break;
case 2:// o przeciwnych znakach
//-5-4= -(5+4)=-9
temp.sign='-';
temp.add(lhs,rhs);
break;
case 3:// obie dodatnie
//5-4= 5-4=1;
temp.subtract(lhs,rhs);
break;
default:
throw;
} else //np |-4|>|5|=false
switch(flag) {
case 0:
// -4-(-5)= -(4-5)=(5-4)=1
temp.subtract(rhs,lhs); //zmieniona kolejność funkcji
// temp.sign='-';
break;
case 1:// o przeciwnych znakach
//4-(-5)= 4+5=9
temp.add(rhs,lhs);//zmieniona kolejność funkcji
break;
case 2:// o przeciwnych znakach
//-4-5= -(5+4)=-9
temp.sign='-';
temp.add(rhs,lhs);//zmieniona kolejność funkcji
break;
case 3:// obie dodatnie
//4-5= -(5-4)=-1;
temp.sign='-';
temp.subtract(rhs,lhs);//zmieniona kolejność funkcji
break;
default:
throw;
}
return temp;
}
std::ostream & operator << (std::ostream & os, const BigNum & bn) {
size_t tabsize=bn.size;
//char * tab = bn.ptrLgNr;
os<< "(rozmiar Tablicy "<<tabsize<<") ";
std::cout<<"cout znak"<<bn.sign<<std::endl;
bn.sign=='-'?os<<'-':os<<'+';
for(size_t i=tabsize-1; i<tabsize; i--)
os<<(short)bn.ptrLgNr[i];
os<<std::flush;
return os;
}
void BigNum::add(const BigNum & ptrBigger,const BigNum &ptrShorter) {
size_t bigger = ptrBigger.size;
size_t lower = ptrShorter.size;
char mem{};
size_t i=0;
/// for(; i+lower<bigger; i++) { // pamiętać by sumować przy size_t -> i<bigger-lower <-tak pętla niekonczona
for(; i<lower; i++) {
// o((int)ptrBigger.ptrLgNr[i])o((int)ptrShorter.ptrLgNr[i])o(ptrBigger.ptrLgNr[i]+ptrShorter.ptrLgNr[i])o(ptrBigger.ptrLgNr[i]+ptrShorter.ptrLgNr[i]+mem)
mem=ptrBigger.ptrLgNr[i]+ptrShorter.ptrLgNr[i]+mem;
ptrLgNr[i]=mem%10;
// o((int)mem)
mem/=10;
// o((int)mem)
}
while(mem)
if(i<bigger) {
mem=ptrBigger.ptrLgNr[i]+mem;
ptrLgNr[i]=mem%10;
mem/=10;
i++;
} else {
ptrLgNr[i]=1; //mem%10=1;
break;
}
for(; i<bigger; i++) {
ptrLgNr[i]=ptrBigger.ptrLgNr[i];
}
while(!ptrLgNr[size-1])
size--; //je¿eli pierwsze 0
}
void BigNum::subtract(const BigNum & ptrBigger,const BigNum &ptrShorter) {
size_t bigger = ptrBigger.size;
size_t lower = ptrShorter.size;
char mem{};
size_t i=0;
/// for(; i+lower<bigger; i++) { // pamiętać by sumować przy size_t -> i<bigger-lower <-tak pętla nieskończona
for(; i<lower; i++) {
if(ptrBigger.ptrLgNr[i]>ptrShorter.ptrLgNr[i]) {
ptrLgNr[i]=ptrBigger.ptrLgNr[i]-ptrShorter.ptrLgNr[i]+mem;
mem=0;
} else if(ptrBigger.ptrLgNr[i]<ptrShorter.ptrLgNr[i]) {
ptrLgNr[i]=ptrBigger.ptrLgNr[i]+10-ptrShorter.ptrLgNr[i]+mem;
mem=-1;
} else if(mem) {
ptrLgNr[i]=10+mem;
} else
ptrLgNr[i] = 0;
}
while(mem) // mem = -1;
if(i<bigger) // by nie wyjść za tablicę
if(ptrBigger.ptrLgNr[i]) {//ptrBigger.ptrLgNr[i] =(1,9);
ptrLgNr[i]=ptrBigger.ptrLgNr[i]+mem;
mem=0; //break;
i++;
} else {
ptrLgNr[i]=9; //0-1 => 10 - 1 =9, m=-1
} else
break;
for(; i<bigger; i++) {
ptrLgNr[i]=ptrBigger.ptrLgNr[i];//przepisujemy pozostałe liczby
}
while(!ptrLgNr[size-1])
if(size>1)
size--; //jeżeli pierwsze 0
else
break;
shrinkToFit();
if(size==1&&ptrLgNr[0]==0) sign='+'; // jeżeli zero zmień znak na '+'
//sign='+';
return;
}
void BigNum::shrinkToFit() {
if(!ptrLgNr)
throw std::bad_alloc();
char* newOne=nullptr;
newOne=new char[size+1] {}; // +1 zarezerwowany dla znaku '\0'//throw std::bad_alloc();
newOne[size]=0;
for(size_t i=0; i<size; i++)
newOne[i]= ptrLgNr[i];
delete [] ptrLgNr;
ptrLgNr=newOne;
newOne=nullptr;
return;
}
bool BigNum::graterAbs(const BigNum &rhs) {
if(size>rhs.size)
return 1;
if(size<rhs.size)
return 0;
for(size_t i=size-1; i<size; i--)
if(ptrLgNr[i]!=rhs.ptrLgNr[i])
return ptrLgNr[i]>rhs.ptrLgNr[i]?1:0;
return 0;
}
bool BigNum::graterAbs(const BigNum &lhs,const BigNum &rhs) {
if(lhs.size>rhs.size)
return 1;
if(lhs.size<rhs.size)
return 0;
for(size_t i=lhs.size-1; i<lhs.size; i--)
if(lhs.ptrLgNr[i]!=rhs.ptrLgNr[i])
return lhs.ptrLgNr[i]>rhs.ptrLgNr[i]?1:0;
return 0;
}
/*///////////////////////////////////////////////////////////////////////////////
char* newOne = new char[size + 1];
newOne[size] = 0;
for(size_t i = 0; i < size; i++)
newOne[i] = ptrLgNr[i];
///////////////////////////////////////////////////////////////////////////////
newOne=new char[size+1] {}; // +1 zarezerwowany dla znaku '\0'
newOne[size]=0;
if(newOne)
for(size_t i=0; i<size; i++)
newOne[i]= ptrLgNr[i];
else
throw std::bad_alloc(); // jeżeli nie udał
//////////////////////////////////////////////////////////////////////////////*/
#ifndef BigNum_H
#define BigNum_H
#define o(x) std::cout<<'\n'<<#x<<'='<<x<<std::endl;
#define n(x) std::cout<<'\n'<<#x<<std::endl;
#include <iostream>
//#include <algorithm>
#include <cstring> //memcopy
#include "Error.h"
class BigNum {
public:
BigNum(const std::string& longNum = "0");
BigNum(const BigNum & other);
BigNum(const int& num);
//BigNum(std::string num); // is ambiguous
// BigNum(const char& num); // is ambiguous
BigNum& operator=(const BigNum& other);
BigNum& operator=(const int& num);
BigNum& operator=(std::string num);
BigNum& operator=(const char & num);
virtual ~BigNum();
//private:
public:
///**friend by nie robi� funkcji du�ej ilo�ci get() i set() **********************************//////
friend BigNum operator + (const BigNum& lhs,const BigNum& rhs);
friend BigNum operator - (const BigNum& lhs,const BigNum& rhs);
friend std::ostream & operator << (std::ostream & os, const BigNum & bn);
///**funkcje prywatne bo użycie publiczne moze dać dziwne rezultaty ************************//////
void subtract(const BigNum & ptrBigger,const BigNum &ptrShorter);
void add(const BigNum & ptrBigger,const BigNum &ptrShorter);
void realloc(char ** old=nullptr,const size_t & newsize=0);
void shrinkToFit();
bool graterAbs(const BigNum &rhs);
bool graterAbs(const BigNum &lhs,const BigNum &rhs);
///**prywatne zmienne************************************************************************//////
size_t size{};
size_t capacity{};
char * ptrLgNr{nullptr};
volatile char sign{'+'};
bool correct =true;
//void add(const BigNum & ptrBigger,const BigNum &ptrShorter, BigNum* ptr);
};
#endif // BigNum_H
#ifndef ERROR_H
#define ERROR_H
struct ERROR {
virtual const char*const what()const throw() {return "Error";}
// virtual ~Error(){};
};
struct ErrDim:ERROR {
virtual const char*const what()const throw() {return "Długość nie moze byc zerowa";}
};
struct UnknownSign:ERROR {
virtual const char*const what()const throw() {return "nieznany znak";}
};
struct WrongNum:ERROR {
virtual const char*const what()const throw() {return "Błędna liczba";}
};
#endif // ERROR_H