Level0 - bigint

blabla

Subject

Name: bigint  
Files: bigint.cpp, bigint.hpp

In computer science, a bignum is an object representing an arbitrary precision number. This is useful when you want to store a number bigger than SIZE_MAX without any loss of precision. This is often achieved by storing an array or a string containing the different parts of the numbers.

Create a class bigint that will store an arbitrary precision unsigned integer.

Your class must support addition, comparison, and "digitshift" (like bitshift but instead of shifting the bits, you will shift the digits in base 10, e.g., (42 << 3 = 42000) and (1337 >> 2 = 13).

Your bigInt must be printable with the << operation (in base 10) and output shouldn't contain any leading zeroes.

You will find a main in the directory that must work with your class.

main.cpp

#include <iostream>
#include "bigint.hpp"

int main() {
    const bigint a(42);
    bigint b(21), c, d(1337), e(d);

    std::cout << "a + b: " << a << " + " << b << " = " << (a + b) << std::endl;

    c += a;
    std::cout << "c += a: c = " << c << std::endl;

    std::cout << "++b: " << ++b << std::endl;
    std::cout << "b++: " << b++ << " (après incrémentation: " << b << ")" << std::endl;

    std::cout << "b >> 10: " << b << " >> 10 = " << (b >> 10) << std::endl;

    d <<= 4;
    std::cout << "d <<= 4: d = " << d << std::endl;

    d >>= 2;
    std::cout << "d >>= 2: d = " << d << std::endl;

    std::cout << "d == a: " << (d == a) << std::endl;
    std::cout << "d != a: " << (d != a) << std::endl;
    std::cout << "d <= a: " << (d <= a) << std::endl;
    std::cout << "d > a: " << (d > a) << std::endl;

    return 0;
}

Answer from ChatGPT

bigint.hpp

#ifndef BIGINT_HPP
#define BIGINT_HPP

#include <string>
#include <iostream>

class bigint {
public:
    // Default constructor
    bigint();

    // Constructor taking an unsigned integer
    bigint(unsigned int n);

    // Operators
    bigint operator+(const bigint& other) const;
    bigint& operator+=(const bigint& other);
    bool operator==(const bigint& other) const;
    bool operator!=(const bigint& other) const;
    bool operator<=(const bigint& other) const;
    bool operator>(const bigint& other) const;
    bigint& operator++();     // Pre-increment
    bigint operator++(int);   // Post-increment
    bigint operator<<(int shift) const;
    bigint operator>>(int shift) const;
    bigint& operator<<=(int shift);
    bigint& operator>>=(int shift);

    // Output stream operator
    friend std::ostream& operator<<ostream& os, const bigint& num;

private:
    std::string value;

    // Utility function to convert an unsigned int to a string
    static std::string to_string(unsigned int n);
};

#endif // BIGINT_HPP

bigint.cpp

#include "bigint.hpp"
#include <sstream>  // Used for int to string conversion in C++98
#include <algorithm> // Used for std::reverse

// Utility function to convert an unsigned int to a string (C++98)
std::string bigint::to_string(unsigned int n) {
    std::ostringstream oss;
    oss << n;
    return oss.str();
}

// Default constructor
bigint::bigint() : value("0") {}

// Constructor taking an unsigned integer
bigint::bigint(unsigned int n) : value(to_string(n)) {}

// Addition of two bigints
bigint bigint::operator+(const bigint& other) const {
    std::string result;
    int carry = 0;
    int maxLength = (value.size() > other.value.size()) ? value.size() : other.value.size();
    
    for (int i = 0; i < maxLength || carry; ++i) {
        int aDigit = (i < value.size()) ? value[value.size() - i - 1] - '0' : 0;
        int bDigit = (i < other.value.size()) ? other.value[other.value.size() - i - 1] - '0' : 0;
        int sum = aDigit + bDigit + carry;
        result += (sum % 10) + '0';
        carry = sum / 10;
    }
    
    std::reverse(result.begin(), result.end());
    return bigintstoul(result);
}

// Addition with assignment
bigint& bigint::operator+=(const bigint& other) {
    *this = *this + other;
    return *this;
}

// Equality comparison
bool bigint::operator==(const bigint& other) const {
    return value == other.value;
}

// Inequality comparison
bool bigint::operator!=(const bigint& other) const {
    return !(*this == other);
}

// Less than or equal to operator
bool bigint::operator<=(const bigint& other) const {
    return value.size() < other.value.size() || (value.size() == other.value.size() && value <= other.value);
}

// Greater than operator
bool bigint::operator>(const bigint& other) const {
    return !(*this <= other);
}

// Pre-increment
bigint& bigint::operator++() {
    *this += bigint(1);
    return *this;
}

// Post-increment
bigint bigint::operator++(int) {
    bigint temp = *this;
    ++(*this);
    return temp;
}

// Left digit shift
bigint bigint::operator<<(int shift) const {
    bigint result = *this;
    result.value.append(shift, '0');
    return result;
}

// Right digit shift
bigint bigint::operator>>(int shift) const {
    bigint result = *this;
    if (shift >= result.value.size()) {
        result.value = "0";
    } else {
        result.value.erase(result.value.size() - shift);
    }
    return result;
}

// Left digit shift with assignment
bigint& bigint::operator<<=(int shift) {
    value.append(shift, '0');
    return *this;
}

// Right digit shift with assignment
bigint& bigint::operator>>=(int shift) {
    if (shift >= value.size()) {
        value = "0";
    } else {
        value.erase(value.size() - shift);
    }
    return *this;
}

// Output stream operator
std::ostream& operator<<ostream& os, const bigint& num {