#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"),
{
n("_________________________________________________________________________________________________________")
n("obiekt konstruktor bez stringa");
BigNum a;
o(a)
}
{
n("_________________________________________________________________________________________________________")
n("obiekt konstruktor ");
BigNum a(BigNum("15"));
o(a)
}
{
n("_________________________________________________________________________________________________________")
n("obiekt konstruktor z stringiem");
std::string stra = "123";
BigNum a("123");o(a)
BigNum b(stra);o(b)
}
{
n("_________________________________________________________________________________________________________")
n("sam konstruktor zwykły konstruktor z stringiem");
o(BigNum("123"));
}
{
n("sam konstruktor zwykły konstruktor z bez stringa stringiem");
o(BigNum());
}
{
n("_________________________________________________________________________________________________________")
n(" zwykły konstruktor int");
o(BigNum(-111));
}
{
n("_________________________________________________________________________________________________________");
n("konstruktor z int BigNum a=100");
BigNum a=-100;
o(a)
}
{
n("_________________________________________________________________________________________________________")
n(" konstruktor kopiujący char BigNum a=\"10\"");
BigNum a="10";
o(a)
}
{
n("_________________________________________________________________________________________________________")
n(" konstruktor kopiujący char BigNum a=BigNum(\"101\")");
BigNum b("101");
BigNum a = b;
o(a)
}
{
n("_________________________________________________________________________________________________________")
n(" konstruktor char BigNum a=(std::string)\"-11\"");
BigNum a=(std::string)"-11";
o(a)
}
{n("========================================================================")
BigNum a,b;
{
n("_________________________________________________________________________________________________________")
n("operator przypisania int a=-12")
a=-12;
o(a)
}
{
n("_________________________________________________________________________________________________________")
n("operator przypisania char a=\"-13\"")
b="-13";
o(b)
}
}n("========================================================================")
// BigNum a(5),d("-4"),e=7,f=BigNum("-5"),g(f);
// o(a);
// o(e);
// o(f)
//// BigNum
////a=5,b=4,c=-5,d=-4;
// BigNum b,c;//,c(10);
// o(b)
// c=5;b="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);o(c)
// 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() } {
// BigNum::BigNum(const std::string& longNum) :size{ longNum.size() } {
// n("BigNum::BigNum(const std::string& longNum)")
// constructor(longNum);
//}
BigNum::BigNum(std::string longNum) :size{ longNum.size() } {
n("BigNum::BigNum(std::string longNum)")
constructor(longNum);
// 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] {};
// // ptrLgNr[size]=0;
//}
//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++) {
// if (*it >= '0' && *it <= '9') { ptrLgNr[last - it] = *it - '0'; }
// else
// switch (*it) {
// case '-':
// //ptrLgNr[last-it]=*it;
// if (it == longNum.cbegin())
// ptrLgNr[last - it] = 0;
// else
// throw WrongNum();
// break;
// case 0:
// ptrLgNr[last - it] = *it;
// break;
// default:
// correct = false;
// throw WrongNum();
// break;
// }
// }
}
BigNum::BigNum(const BigNum& other) { /*:size{other.size}*/
if (ptrLgNr) {
delete[] ptrLgNr;
ptrLgNr = nullptr;
}
n("BigNum::BigNum(const BigNum & other)")
if (other.size) {
ptrLgNr = new char[other.size + 1] {};
size = other.size;
for (size_t i = 0; i < size; i++) {
ptrLgNr[i] = other.ptrLgNr[i];
}
// memcpy(ptrLgNr,other.ptrLgNr,other.size);
}
else {
std::cerr << "zły wymiar" << std::endl;
throw ErrDim();
}
}
BigNum::BigNum(BigNum&& other) { /*:size{other.size}*/
if (ptrLgNr) {
delete[] ptrLgNr;
ptrLgNr = nullptr;
}
n("BigNum::BigNum(const BigNum && other)");
size = other.size;
capacity = other.capacity;
ptrLgNr = other.ptrLgNr;
other.ptrLgNr = nullptr;
sign = other.sign;
correct = other.correct;
}
BigNum::BigNum(const int& num) {
n("BigNum::BigNum(const int& num)")
std::string temp = std::to_string(num);
size = temp.size();
constructor(temp);
}
BigNum::BigNum(const char* num) {
size = std::string(num).size();
constructor(std::string(num));
}
BigNum::~BigNum() {
if (ptrLgNr)
delete[]ptrLgNr;
n("usnalem sie")
n("________________________________________________________________________________________________________")
}
BigNum& BigNum::operator=(const BigNum& rhs) {
n("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 = 0; 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=(BigNum&& rhs) {
n("BigNum& BigNum::operator=(const BigNum&& rhs)")
if (this == &rhs)
return *this; // handle self assignment
delete [] ptrLgNr;
ptrLgNr = rhs.ptrLgNr;
rhs.ptrLgNr = nullptr;
size = rhs.size;
capacity = rhs.capacity;
sign = rhs.sign;
correct = rhs.correct;
return *this;
}
//BigNum& BigNum::operator=(const int& num) {
// n("BigNum& BigNum::operator=(const int& num)")
// delete [] ptrLgNr;
// ptrLgNr =nullptr;
// std::string temp=std::to_string(num);
// size=temp.size();
// constructor(temp);
// 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;
if (lhs.size > 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;
}
void BigNum::constructor(std::string longNum) {
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.begin(), end = longNum.end(), last = end - 1; it != end; it++) {
if (*it <= '9' && *it >= '0') { ptrLgNr[last - it] = *it - '0'; }
else
switch (*it) {
case '-':
if (it == longNum.cbegin())
ptrLgNr[last - it] = 0;
else
throw WrongNum();
break;
case 0:
ptrLgNr[last - it] = *it;
break;
default:
correct = false;
throw WrongNum();
break;
}
}
}
/*///////////////////////////////////////////////////////////////////////////////
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 <string>
#include "Error.h"
class BigNum {
public:
// BigNum(const std::string& longNum);
BigNum(std::string longNum="0");
BigNum(const int& num);
BigNum(const char* num);
BigNum(const BigNum & other);
BigNum(BigNum && other);
BigNum& operator=(const BigNum& other);
BigNum& operator=( BigNum&& other);
// BigNum& operator=(const int& 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);//ewentualnie print()
///**funkcje prywatne bo użycie publiczne może 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);
void constructor(std::string longNum);
///**prywatne zmienne************************************************************************//////
size_t size{};
size_t capacity{};
char * ptrLgNr{nullptr};
volatile char sign{'+'};
bool correct =true;
};
#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