klasa BigInt która będzie przechowywać liczbę i pozwalać za pomocą metod składowych typu add(const BigInt&) oraz subtract(const BigInt&) na obliczenia

0

Cześć, dostałem zadanie aby napisać klasę BigInt która będzie przechowywać liczbę i pozwalać za pomocą metod składowych typu add(const BigInt&) oraz
subtract(const BigInt&) na obliczenia. Nie mogę jednak zrozumieć o co chodzi w const BigInt& i jak dokładnie takie metody powinny działać.

Napisałem program tego typu:

#include <iostream>
using namespace std;
class BigInt
{
public:
    int number=0;
    int add(const int value)
    {
        number+=value;
        return number;
    }
    int subtract(const int value)
    {
        number-=value;
        return number;
    }
};

int main()
{
    BigInt bigInt;
    bigInt.add(5);
    bigInt.subtract(2);

    cout<<"bigInt.number"<<endl;
}

ale chyba nie do końca o to w tym chodzi. Mógłby ktoś pomóc lepiej zrozumieć to zadanie?

6

int number

Obawiam sie że jak BigInt to jednak trzeba trzymać liczby za pomocą długich stringów i wykonywać działania "pisemnie"

0

Masz rację, uprościłem zadanie ze stringa na int żeby po prostu lepiej zrozumieć o co chodzi, mógłbyś wyjaśnić jak całość powinna działać ?

1

Pewnie najlepiej byłoby w ogóle przeładować sobie operatory =, +, -, *,/ żebyś mógł robić jakieś:

BigInt x("1");
BigInt y("2");
BigInt z = x+y;

Ale alternatywnie możesz też mieć jakieś bardziej klasyczne:

BigInt x("1");
BigInt y("2");
y.add(x);
x.subtract(y);
0

Ok, czyli przeciążam operator + i - a następnie piszę 2 metody na dodawanie i odejmowanie w których pisemnie dodaje/odejmujęliczby ?

I jeszcze takie pytanie mam, co oznacza w tej metodzie odwołanie do całej klasy add(const BigInt&) ? Do czego to będzie potrzebne ?

0

Stringi OK, ale tylko w konstruktorze. Po co do reprezentacji cyfry (0-9) marnować cały bajt? Sugerowałbym użyć vector<int>

0

@Outer

co oznacza w tej metodzie odwołanie do całej klasy add(const BigInt&)

No bo przecież chcesz odejmować BigInt od BigInta tak jak w przykładzie który pokazałem. Więc siłą rzeczy argumentem takiej funkcji dodawania/odejmowania musi być jakiś BigInt

0

Czuję że to jest banalne ale nie mogę tego zrozumieć, napisałem na szybko taką klasę z przeciążonym operatorem +:

class BigInt
{
public:
int number;
BigInt()
{}
BigInt(int a):number(a)
{
}
BigInt operator+(BigInt &obj)
{
BigInt wynik;
wynik.number=number+obj.number;
return wynik;
}
};

int main()
{
BigInt x(5);
BigInt y(8);
BigInt z;
z=x+y;

cout<<z.number<<endl;

}

I nie mogę zrozumieć jak odwołując się do całej klasy miałbym dodać/odjąć jakąś wartość.

3

Nie mogę jednak zrozumieć o co chodzi w const BigInt&

To po prostu optymalizacja.

Mając funkcję:

void Funkcja( BigInt value )
{
    value.number = 100; // zmiana wartości
}

za każdym razem kiedy wywołasz funkcję to musi zostać skopiowany cały obiekt ( a to przy złożoności klasy może spowodować problem z wydajnością )

int main()
{
    BigInt someValue;
    Funkcja( someValue ); // kopiuje obiekt - obiekt someValue pozostaje bez zmian po wywołaniu funkcji
    Funkcja( someValue ); // kopiuje obiekt - obiekt someValue pozostaje bez zmian po wywołaniu funkcji
    // itd..
}

Żeby tego uniknąć, musisz przekazać obiekt przez referencję (w funkcji będziesz ciągle operował na jednym obiekcie). Do tego służy operator &:

void Funkcja( BigInt &value )
{
    value.number = 100; // zmiana wartości
}
int main()
{
    BigInt someValue;
    Funkcja( someValue ); // nie kopiuje obiektu, zamiast tego przekazywany jest do funkcji adres obiektu (referencja) - someValue zostanie zmieniony
    Funkcja( someValue ); // nie kopiuje obiektu, zamiast tego przekazywany jest do funkcji adres obiektu (referencja) - someValue zostanie zmieniony
    // itd..
}

Natomiast powstaje pewien problem: wołając funkcję nie wiesz czy obiekt którym dysponujesz nie zostanie zmieniony przez funkcję. Żeby to uniemożliwić robisz referencję do obiektu, którego nie można zmienić - czyli const &.

void Funkcja( const BigInt &value )
{
    // value.number = 100; - ta linijka już się nie skompiluje, bo obiektu nie można zmienić.
}
int main()
{
    BigInt someValue;
    Funkcja( someValue ); // nie kopiuje obiektu, zamiast tego przekazywany jest do funkcji adres obiektu (referencja) - someValue nie może zostać zmieniony
    Funkcja( someValue ); // nie kopiuje obiektu, zamiast tego przekazywany jest do funkcji adres obiektu (referencja) - someValue nie może zostać zmieniony
    // itd..
}

Taki const & jest jeszcze wymagany, kiedy chcesz przekazać obiekt tymczasowy do funkcji:

Na przykład:

int main()
{
    Funkcja( BigInt() ); // BigInt() tworzy domyślnie skonstruowany obiekt tymczasowy o typie BigInt.
}

To się może przydać kiedy chcesz zrobić na przykład tak:


class BigInt
{
public:    
    BigInt() : number( 0 )
    {
    }
    
    BigInt( int a ) : number( a )
    {
    }
    
    BigInt operator+( const BigInt &obj )
    {
        BigInt wynik;
        wynik.number = number + obj.number;
        return wynik;
    }
    
private:
    int number;
};

int main()
{
    BigInt x( 5 );
    BigInt y = x + BigInt( 10 );
}

Jeszcze tak uściślając:

Nie można przekazać obiektu tymczasowego do zwykłej referencji (nie-const). Można przekazać przez wartość (bez &) - jeśli oczywiście jest konstruktor kopiujący. Albo można też przekazać przez && (tzw Rvalue reference). Jeśli będziesz się uczył C++ jeszcze przez jakieś 5 lat to może do tego kiedyś dojdziesz.

& - Lvalue reference
&& - Rvalue reference

https://en.cppreference.com/w/cpp/language/reference

0

https://wandbox.org/permlink/byFlTfh2vsKNNPYj

#include <iostream>
#include <vector>
#include <iomanip>
 
using namespace std;

auto Factorial(unsigned int x) -> vector<unsigned int>
{
    vector<unsigned int> result;
    result.reserve(128);
    
    result.push_back(1);
    while (x > 1)
    {
        unsigned int c = 0;
        for (auto& d : result)
        {
            auto y = d * x + c;
            d = y % 1000;
            c = y / 1000;
        }
        if (c)
        {
            result.push_back(c);
        }
        --x;
    }
    
    return result;
}

ostream& PrintFrac(ostream& out, const vector<unsigned int>& r)
{
    auto b = rbegin(r);
    auto e = rend(r);
    out << *b++;
    while(b != e)
    {
        out << setfill('0') << setw(3) << *b++;
    }
    return out;
};

    
int main()
{
    unsigned int x;
    while (cin >> x)
    {
        PrintFrac(cout << x << "! = ", Factorial(x)) << endl;
    }
    
    return 0;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1