Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "pch.h"
- #include <iostream>
- #include <vector>
- class natural {
- private:
- std::vector<uint32_t> value;
- public:
- /* Konstruktor bezargumentowy */
- natural::natural() {}
- /* Konstruktor kopiujacy, z uinta */
- natural::natural(const uint32_t a) {
- this->value.push_back(a);
- }
- /* Konstruktor kopiujacy, z vectora */
- natural::natural(const std::vector<uint32_t> &a) {
- this->value = a;
- }
- /* Konstruktor kopiujacy, z natural */
- natural::natural(const natural &a) : value(a.value) {}
- /* Funkcja, ktora dodaje uinta32 do wartosci */
- void natural::push_back(const uint32_t a) {
- this->value.push_back(a);
- }
- /* Funkcja, ktora usuwa element o najwyzszej wadze */
- void natural::pop_back() {
- this->value.pop_back();
- }
- /* liczba elementow */
- unsigned natural::size() {
- return value.size();
- }
- /* operator przypisania */
- void natural::operator=(const natural &x) {
- this->value = x.value;
- }
- /* operator porownania */
- bool natural::operator==(const natural &x) {
- if (value.size() != x.value.size())
- return false;
- else {
- // porownywanie kolejnych elementow
- for (unsigned i = 0; i < x.value.size(); i++)
- if (value[i] != x.value[i])
- return false;
- return true;
- }
- }
- /* operator inkrementacji */
- void natural::operator++() {
- unsigned i = 0;
- bool cIn = true;
- for (; i < this->value.size() && cIn; i++) {
- this->value[i]++;
- cIn = (this->value[i] == 0);
- }
- if (cIn) {
- this->value.push_back(1);
- }
- }
- /* operator dekrementacji */
- void natural::operator--() {
- if (this->value.size() == 0)
- std::cout << "Niezainicjalizowana liczba";
- int i = 0;
- bool bIn = true;
- for (; bIn; i++) {
- bIn = (this->value[i] == 0);
- this->value[i]--;
- }
- }
- /* operator porownania, wiekszy */
- bool natural::operator >(const natural &x) {
- if (this->value.size() > x.value.size())
- return true;
- else if (this->value.size() < x.value.size())
- return false;
- else { //argumenty tej samej dlugosci
- // porownywanie kolejnych elementow od lewej (tych o wyzszej wadze)
- for (int i = this->value.size() - 1; i >= 0; i--)
- if (this->value[i] > x.value[i])
- return true;
- return false;
- }
- }
- /* operator porownania, mniejszy */
- bool natural::operator <(const natural &x) {
- if (this->value.size() < x.value.size())
- return true;
- else if (this->value.size() > x.value.size())
- return false;
- else { //argumenty tej samej dlugosci
- // porownywanie kolejnych elementow od lewej (tych o wyzszej wadze)
- for (int i = this->value.size() - 1; i >= 0; i--)
- if (this->value[i] < x.value[i])
- return true;
- return false;
- }
- }
- /* operator porownania, wiekszy/rowny */
- bool natural::operator >=(const natural &x) {
- unsigned int counter = 0; //licznik rownych elementow
- if (this->value.size() > x.value.size())
- return true;
- else if (this->value.size() < x.value.size())
- return false;
- else { //argumenty tej samej dlugosci
- // sprawdzenie czy jest wiekszy
- for (unsigned int i = this->value.size() - 1; i >= 0; i--) {
- if (this->value[i] > x.value[i])
- return true;
- else if (this->value[i] == x.value[i]) //sprawdzenie czy rowne
- counter++;
- }
- if (counter == this->value.size()) //wszystkie elementy sa rowne
- return true;
- else
- return false;
- }
- }
- /* operator porownania, mniejszy/rowny */
- bool natural::operator <=(const natural &x) {
- unsigned int counter = 0; //licznik rownych elementow
- if (this->value.size() < x.value.size())
- return true;
- else if (this->value.size() > x.value.size())
- return false;
- else { //argumenty tej samej dlugosci
- // sprawdzenie czy jest mniejszy
- for (unsigned int i = this->value.size() - 1; i >= 0; i--) {
- if (this->value[i] < x.value[i])
- return true;
- else if (this->value[i] == x.value[i]) //sprawdzenie czy rowne
- counter++;
- }
- if (counter == this->value.size()) //wszystkie elementy sa rowne
- return true;
- else
- return false;
- }
- }
- /* wypisywanie wartosci */
- void natural::print() {
- for (int i = value.size() - 1; i >= 0; i--)
- std::cout << value[i] << " ";
- std::cout << "\n";
- }
- /* usuwanie wiodacego zera */
- void natural::eraseLeadingZeroIfExists() {
- if ((this->value.size() - 1) == 0) //jesli elementem o najwyzszej wadze jest 0
- this->value.pop_back(); //trzeba je usunac, zaburza wykonanie porownania
- }
- /* operacje arytmetyczne */
- /* dodawanie */
- void natural::add(const natural &x, const natural &y) {
- bool cIn, cOut; //przeniesienia na konkretnych pozycjach
- uint32_t temp; //przechowywanie sumy
- unsigned i = 0; //indeksowanie
- const natural *shorterArg, *longerArg; //zmienne na krotszy i dluzszy argument
- if (x.value.size() >= y.value.size()) { //rownej dlugosci lub x dluzszy od y
- longerArg = &x;
- shorterArg = &y;
- }
- else { //y dluzszy od x
- longerArg = &y;
- shorterArg = &x;
- }
- // dla kazdego elementu w zasiegu krotszego argumentu
- for (cIn = false; i < shorterArg->value.size(); i++) {
- temp = longerArg->value[i] + shorterArg->value[i];
- cOut = (temp < longerArg->value[i]); //sprawdzenie czy uint sie "nie przekrecil"
- if (cIn) {
- temp++;
- cOut |= (temp == 0); // cOut | temp
- }
- this->value.push_back(temp); // zapisanie wyniku
- cIn = cOut; // przeniesienie w nastepnej iteracji
- }
- //w zasiegu dluzszego argumentu z przeniesieniem
- for (; i < longerArg->value.size() && cIn; i++) {
- temp = longerArg->value[i] + 1;
- cIn = (temp == 0); //max val + 1 = 0
- this->value.push_back(temp);
- }
- //w zasiegu dluzszego argumentu bez przeniesienia
- for (; i < longerArg->value.size(); i++)
- this->value.push_back(longerArg->value[i]); //przepisywanie
- //Dodatkowy element w przypadku nadmiaru
- if (cIn)
- this->value.push_back(1);
- }
- /* odejmowanie */
- void natural::subtract(const natural &x, const natural &y) {
- bool bIn, bOut; //pozyczki na konkretnych pozycjach
- uint32_t temp; //przechowywanie roznicy
- unsigned i = 0; //indeksowanie
- for (bIn = false; i < y.value.size(); i++) {
- temp = x.value[i] - y.value[i];
- bOut = (temp > x.value[i]); //sprawdzenie czy uint sie "nie przekrecil"
- if (bIn) {
- bOut |= (temp == 0); // bOut | temp
- temp--;
- }
- this->value.push_back(temp); // zapisanie wyniku
- bIn = bOut; // pozyczka w nastepnej iteracji
- }
- // dalsze pozyczki
- for (; i < x.value.size() && bIn; i++) {
- bIn = (x.value[i] == 0);
- this->value.push_back(x.value[i] - 1);
- }
- if (bIn) {
- this->value.clear();
- std::cout << "Wynik odejmowania ujemny\n";
- }
- else //dalsze przepisywanie odjemnej, bez zmian
- for (; i < x.value.size(); i++)
- this->value.push_back(x.value[i]);
- }
- /* mnozenie */
- void natural::multiply(const natural &x, const natural &y) {
- int cIn = 0;
- int cOut = 0;
- uint32_t temp = 0;
- std::vector<uint32_t> tempMod;
- natural tempVec;
- natural tempNat;
- int longerArg = 0;
- if (x.value.size() >= y.value.size())
- longerArg = x.value.size();
- else longerArg = y.value.size();
- unsigned long long longtemp;
- for (unsigned i = 0; i < x.value.size(); i++) {
- for (int k = 0; k < i; k++) {
- tempVec.value.insert(tempVec.value.begin(), 0);
- }
- for (unsigned j = 0; j < y.value.size(); j++) {
- longtemp = x.value[i] * y.value[j] + cIn;
- temp = longtemp;
- tempVec.value.insert(tempVec.value.begin() + i + j, temp);
- if (temp == longtemp) {
- cIn = 0;
- }
- else {
- cIn = longtemp / 4294967295;
- }
- temp = 0;
- }
- tempMod = this->value;
- tempNat.value = tempMod;
- this->value.clear();
- this->add(tempNat, tempVec);
- tempVec.value.clear();
- tempMod.clear();
- }
- }
- // prymitywny algorytm dzielenia
- void natural::divide(const natural &x, const natural &y) {
- natural divident(x); //kopia do dzialan dzielnej
- natural quotient(0); //przechowywanie ilorazu, quotient
- natural temp;
- while (divident.operator>(y)) { //powinno byc >= ale samo > to mniej operacji
- temp.subtract(divident, y);
- divident.value = temp.value; //kopiowanie wartosci
- divident.print();
- temp.value.clear(); //zwalnianie pamieci z temp
- quotient.operator++();
- divident.eraseLeadingZeroIfExists();
- }
- if (divident.operator==(y)) { //ostatnie porownanie
- temp.subtract(divident, y);
- divident.value = temp.value; //kopiowanie wartosci
- temp.value.clear(); //zwalnianie pamieci z temp
- quotient.operator++();
- }
- this->value = quotient.value;
- temp.value.clear(); //zwalnianie pamieci z temp
- divident.value.clear();
- }
- };
- class smNum
- {
- bool sign; //false +, true -
- natural module; //modul reprezentowany przez liczbe naturalna
- public:
- bool static getSign(smNum x) {
- return x.sign;
- }
- natural static getModule(smNum x) {
- return x.module;
- }
- /* Konstruktor bezargumentowy */
- smNum::smNum()
- : sign(false),
- module() { }
- /* Konstruktor kopiujacy, z uinta */
- smNum::smNum(const uint32_t a) {
- sign = false;
- this->module.push_back(a);
- }
- /* Konstruktor sam modul */
- smNum::smNum(const std::vector<uint32_t> &a) {
- sign = false;
- module = natural(a);
- }
- /* Konstruktor znak-modul */
- smNum::smNum(bool si, const std::vector<uint32_t> &a) {
- sign = si;
- module = natural(a);
- }
- /* Konstruktor kopiujacy z smNum */
- smNum::smNum(const smNum &b)
- : sign(b.sign),
- module(b.module) { }
- /* Konstruktor kopiujacy znak + natural */
- smNum::smNum(const bool si, const natural &n)
- : sign(si),
- module(n) { }
- /* Konstruktor kopiujacy z natural */
- smNum::smNum(const natural &n)
- : sign(false),
- module(n) { }
- /* Konstruktor z konwersja z typu long long */
- smNum::smNum(long long value)
- {
- if (value < 0) {
- sign = true;
- module = natural(0);
- }
- else {
- sign = false;
- }
- while (value) {
- module.push_back((uint32_t)(value));
- }
- }
- /* wypisywanie wartosci */
- void smNum::print() {
- if (sign)
- std::cout << "- ";
- else
- std::cout << "+ ";
- module.print();
- }
- /* operator przypisania */
- void smNum::operator=(const smNum &x) {
- this->sign = x.sign;
- this->module = x.module;
- }
- /* operator porownania */
- bool smNum::operator==(const smNum &x) {
- if (this->sign != x.sign) //jesli znaki sa rozne false
- return false;
- else //porownanie wartosci
- if (this->module == x.module)
- return true;
- else
- return false;
- }
- /* operator inkrementacji */
- void smNum::operator++() {
- if (!sign) //dodatnie
- this->module.operator++();
- else //ujemne
- this->module.operator--();
- }
- /* operator dekrementacji */
- void smNum::operator--() {
- if (!sign) //dodatnie
- this->module.operator--();
- else //ujemne
- this->module.operator++();
- }
- /* operator porownania, wiekszy */
- bool smNum::operator >(const smNum &x) {
- if (this->sign != x.sign) { //znaki rozne
- if (this->sign == 0 && x.sign == 1) //x jest liczba ujemna
- return true;
- else
- return false; //x dodatnie a liczba ujemna
- }
- else { //znaki zgodne
- if (this->sign == 0) { //obie liczby dodatnie
- if (this->module > x.module)
- return true;
- else
- return false;
- }
- else { //obie liczby ujemne
- if (this->module < x.module)
- return true;
- else
- return false;
- }
- }
- }
- /* operator porownania, mniejszy */
- bool smNum::operator <(const smNum &x) {
- if (this->sign != x.sign) { //znaki rozne
- if (this->sign == 0 && x.sign == 1) //x jest liczba ujemna
- return false;
- else
- return true; //x dodatnie a liczba ujemna
- }
- else { //znaki zgodne
- if (this->sign == 0) { //obie liczby dodatnie
- if (this->module < x.module)
- return true;
- else
- return false;
- }
- else { //obie liczby ujemne
- if (this->module > x.module)
- return true;
- else
- return false;
- }
- }
- }
- /* operator porownania, wiekszy/rowny */
- bool smNum::operator >=(const smNum &x) {
- if (this->sign != x.sign) { //znaki rozne
- if (this->sign == 0 && x.sign == 1) //x jest liczba ujemna
- return true;
- else
- return false; //x dodatnie a liczba ujemna
- }
- else { //znaki zgodne
- if (this->sign == 0) { //obie liczby dodatnie
- if (this->module >= x.module)
- return true;
- else
- return false;
- }
- else { //obie liczby ujemne
- if (this->module <= x.module)
- return true;
- else
- return false;
- }
- }
- }
- /* operator porownania, mniejszy/rowny */
- bool smNum::operator <=(const smNum &x) {
- if (this->sign != x.sign) { //znaki rozne
- if (this->sign == 0 && x.sign == 1) //x jest liczba ujemna
- return false;
- else
- return true; //x dodatnie a liczba ujemna
- }
- else { //znaki zgodne
- if (this->sign == 0) { //obie liczby dodatnie
- if (this->module <= x.module)
- return true;
- else
- return false;
- }
- else { //obie liczby ujemne
- if (this->module >= x.module)
- return true;
- else
- return false;
- }
- }
- }
- smNum smNum::operator+(smNum x) {
- smNum result;
- smNum arg(this->sign, this->module);
- result.add(arg, x);
- return result;
- }
- smNum smNum::operator-(smNum x) {
- smNum result;
- smNum arg(this->sign, this->module);
- result.sub(arg, x);
- return result;
- }
- smNum smNum::operator*(smNum x) {
- smNum result;
- smNum arg(this->sign, this->module);
- result.mul(arg, x);
- return result;
- }
- smNum smNum::operator/(smNum x) {
- smNum result;
- smNum arg(this->sign, this->module);
- result.div(arg, x);
- return result;
- }
- /* operacje arytmetyczne */
- // dodawanie
- void smNum::add(smNum x, smNum y) {
- if (x.sign == y.sign) { //znaki zgodne
- this->sign = x.sign;
- this->module.add(x.module, y.module);
- }
- else { //znaki niezgodne
- if (x.module >= y.module) {
- this->sign = x.sign;
- this->module.subtract(x.module, y.module);
- }
- else
- {
- this->sign = y.sign;
- this->module.subtract(y.module, x.module);
- }
- }
- }
- // odejmowanie
- void smNum::sub(smNum x, smNum y) {
- if (x.sign == y.sign) { //znaki zgodne
- if (x.module >= y.module) {
- this->sign = x.sign;
- this->module.subtract(x.module, y.module);
- }
- else
- {
- this->sign = !(x.sign);
- this->module.subtract(y.module, x.module);
- }
- }
- else { //znaki niezgodne
- this->sign = x.sign;
- if (x.sign == 0) {
- this->module.add(x.module, y.module);
- }
- else
- {
- this->module.add(x.module, y.module);
- }
- }
- }
- // mnozenie
- void smNum::mul(smNum x, smNum y) {
- if (x.sign == y.sign)
- this->sign = 0;
- else
- this->sign = 1;
- this->module.multiply(x.module, y.module);
- }
- // prymitywny algorytm dzielenia
- void smNum::div(smNum x, smNum y) {
- if (x.sign == y.sign)
- this->sign = 0;
- else
- this->sign = 1;
- this->module.divide(x.module, y.module);
- }
- };
- bool equals(const smNum &x, const smNum &y) {
- if (x.getSign(x) != y.getSign(y)) //jesli znaki sa rozne false
- return false;
- else //porownanie wartosci
- if (x.getModule(x) == y.getModule(y))
- return true;
- else
- return false;
- }
- int Factorial(int n) {
- int result = 1;
- for (int i = 1; i <= n; i++) {
- result *= i;
- }
- return result;
- }
- TEST(TestDodawania, Dodawanie) {
- std::vector<uint32_t> vect;
- std::vector<uint32_t> vect2;
- vect.push_back(55);
- vect.push_back(1);
- vect2.push_back(16);
- vect2.push_back(1);
- std::vector<uint32_t> vect3;
- vect3.push_back(2);
- vect3.push_back(71);
- smNum wynik;//(vect3);
- smNum a1(vect);
- smNum a2(vect2);
- wynik.add(a1, a2);
- smNum a3;
- a3.add(a1, a2);
- a3.print();
- wynik.print();
- ASSERT_TRUE(equals(a3,wynik));
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement