I have written a BigInt class for c++, but I am unable to use the class as an index for arrays.
Example:
int main() {
int array[5] = {4, 6, 2, 9, 0};
BigInt index = 1;
std::cout << array[index] << std::endl;
}
This results in:
error: no match for 'operator[]' (operand types are 'int [5]' and 'BigInt')
cout << array[index] << endl;
^
I tried implementing the following functions, but to no avail.
int operator[] (BigInt &value) {
return (int) value;
}
explicit operator int() {
int result = 0;
for (auto i : digits)
result = result * 10 + i;
return result;
}
I am sure operator[] is used when the class itself is an iterable, so that's pointless.
And explicit operator int() works, but only when I cast the BigInt as int like array[(int) index]
Removing explicit from operator int() works perfectly, except that I can no longer can perform operations involving both int and BigInt
// ...
operator int() {
int result = 0;
for (auto i : digits)
result = result * 10 + i;
return result;
}
// ...
int main() {
int array[5] = {4, 6, 2, 9, 0};
BigInt index = 1;
std::cout << array[index] << std::endl; // Works fine
std::cout << (index == 1) << std::endl; // Doesn't work
}
The above results in the following error:
error: ambiguous overload for 'operator==' (operand types are 'BigInt' and 'int')
cout << (index == 1) << endl;
~~~~~ ^~ ~
How can I overcome these errors?
Thanks!
EDIT:
The BigInt class is as follows:
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
class BigInt {
public:
std::vector<unsigned short> digits;
bool negative;
BigInt(){
this -> digits = {0};
this -> negative = false;
}
BigInt(const BigInt &other){
this -> digits = other.digits;
this -> negative = other.negative;
}
BigInt(std::string other) {
if (other.size() == 0) {
*this = BigInt();
return;
}
std::reverse(other.begin(), other.end());
negative = false;
while (other.back() == '-') {
negative = !negative;
other.pop_back();
}
digits.clear();
for (char c : other)
digits.push_back(c - '0');
(*this).trim();
}
BigInt(const char *other) {
*this = (std::string) other;
}
template<typename T>
BigInt(const T &other) {
*this = to_std::string(other);
}
friend bool operator== (const BigInt &a, const BigInt &b) {
if (a.negative != b.negative || a.digits.size() != b.digits.size())
return false;
for (int i = 0; i < a.digits.size(); i++)
if (a.digits[i] != b.digits[i])
return false;
return true;
}
friend bool operator!= (const BigInt &a, const BigInt &b) {
return !(a == b);
}
friend bool operator< (const BigInt &a, const BigInt &b) {
if (a.negative && b.negative) return (-a) > (-b);
if (a.negative && !b.negative) return true;
if (!a.negative && b.negative) return false;
if (a.digits.size() < b.digits.size()) return true;
if (a.digits.size() > b.digits.size()) return false;
for (int i = a.digits.size() - 1; i >= 0; i--) {
if (a.digits[i] < b.digits[i]) return true;
if (a.digits[i] > b.digits[i]) return false;
}
return false;
}
friend bool operator<= (const BigInt &a, const BigInt &b) {
return !(a > b);
}
friend bool operator> (const BigInt &a, const BigInt &b) {
if (a.negative && b.negative) return (-a) < (-b);
if (!a.negative && b.negative) return true;
if (a.negative && !b.negative) return false;
if (a.digits.size() > b.digits.size()) return true;
if (a.digits.size() < b.digits.size()) return false;
for (int i = a.digits.size() - 1; i >= 0; i--) {
if (a.digits[i] > b.digits[i]) return true;
if (a.digits[i] < b.digits[i]) return false;
}
return false;
}
friend bool operator>= (const BigInt &a, const BigInt &b) {
return !(a < b);
}
friend BigInt operator+ (const BigInt &a, const BigInt &b) {
if (a.negative && b.negative) {
return -((-a) + (-b));
} else if (a.negative && !b.negative) {
return b - (-a);
} else if (!a.negative && b.negative) {
return a - (-b);
} else {
BigInt result; result.digits.clear();
int carry = 0;
for (int i = 0; i < std::max(a.digits.size(), b.digits.size()); i++) {
int sum = carry;
if (i < a.digits.size()) sum += a.digits[i];
if (i < b.digits.size()) sum += b.digits[i];
result.digits.push_back(sum % 10);
carry = sum / 10;
}
if (carry)
result.digits.push_back(carry);
result.trim();
return result;
}
}
friend BigInt operator+ (const BigInt &value) {
return value;
}
friend BigInt operator- (const BigInt &a, const BigInt &b) {
if (a.negative && b.negative) {
return b - a;
} else if (a.negative && !b.negative) {
return -((-a) + b);
} else if (!a.negative && b.negative) {
return a + (-b);
} else {
if (a < b)
return -(b - a);
BigInt result; result.digits.clear();
int carry = 0;
for (int i = 0; i < a.digits.size(); i++) {
int dif = a.digits[i] - carry;
if (i < b.digits.size()) dif -= b.digits[i];
if (dif < 0) {
dif += 10;
carry = 1;
} else {
carry = 0;
}
result.digits.push_back(dif);
}
result.trim();
return result;
}
}
friend BigInt operator- (const BigInt &value) {
BigInt result = value;
result.negative = !result.negative;
result.trim();
return result;
}
friend BigInt operator* (const BigInt &a, const BigInt &b) {
BigInt result;
for (int i = 0; i < a.digits.size(); i++) {
BigInt current; current.digits.clear();
for (int j = 0; j < i; j++)
current.digits.push_back(0);
int carry = 0;
for (int j = 0; j < b.digits.size(); j++) {
int cur_val = a.digits[i] * b.digits[j] + carry;
current.digits.push_back(cur_val % 10);
carry = cur_val / 10;
}
if (carry)
current.digits.push_back(carry);
current.trim();
result += current;
}
result.negative = a.negative ^ b.negative;
result.trim();
return result;
}
friend BigInt operator/ (const BigInt &a, const BigInt &b) {
if (b == 0)
throw std::runtime_error("Division by zero");
BigInt fa = abs(a), fb = abs(b);
BigInt result, left_over;
result.negative = a.negative ^ b.negative;
int index = fa.digits.size() - 1;
while (true) {
BigInt cur = left_over; bool first_digit = true;
while (index >= 0 && cur < fb) {
cur = cur * 10 + fa.digits[index--];
if (!first_digit) result *= 10;
first_digit = false;
}
int cur_res = 0;
while (cur >= fb)
cur -= fb, cur_res++;
left_over = cur;
result = result * 10 + cur_res;
if (index < 0)
break;
}
result.trim();
return result;
}
friend BigInt operator% (const BigInt &a, const BigInt &b) {
if (b == 0)
throw std::runtime_error("Division by zero");
BigInt fa = abs(a), fb = abs(b);
BigInt left_over;
int index = fa.digits.size() - 1;
while (true) {
BigInt cur = left_over;
while (index >= 0 && cur < fb)
cur = cur * 10 + fa.digits[index--];
while (cur >= fb)
cur -= fb;
left_over = cur;
if (index < 0)
break;
}
left_over.negative = b.negative;
left_over.trim();
return left_over;
}
friend BigInt pow(BigInt a, BigInt b) {
BigInt result = 1;
while (b) {
if (b % 2)
result = (result * a);
a *= a;
b /= 2;
}
result.trim();
return result;
}
friend BigInt pow(BigInt a, BigInt b, BigInt mod) {
BigInt result = 1;
if (mod == 0)
throw std::runtime_error("Modulo by zero");
while (b) {
if (b % 2)
result = (result * a) % mod;
a = (a * a) % mod;
b /= 2;
}
result.trim();
return result;
}
friend BigInt operator& (BigInt a, BigInt b) {
BigInt result, power = 1;
while (a > 0 && b > 0) {
if (a % 2 && b % 2)
result += power;
power <<= 1;
a >>= 1;
b >>= 1;
}
return result;
}
friend BigInt operator| (BigInt a, BigInt b) {
BigInt result, power = 1;
while (a > 0 || b > 0) {
if (a % 2 || b % 2)
result += power;
power <<= 1;
a >>= 1;
b >>= 1;
}
return result;
}
friend BigInt operator^ (BigInt a, BigInt b) {
BigInt result, power = 1;
while (a > 0 || b > 0) {
if (a % 2 != b % 2)
result += power;
power <<= 1;
a >>= 1;
b >>= 1;
}
return result;
}
friend BigInt operator<< (BigInt a, BigInt b) {return a * pow(2, b);}
friend BigInt operator>> (BigInt a, BigInt b) {return a / pow(2, b);}
BigInt operator++ () {return *this = *this + 1;}
BigInt operator-- () {return *this = *this - 1;}
BigInt operator++ (int) {BigInt result = *this; *this = *this + 1; return result;}
BigInt operator-- (int) {BigInt result = *this; *this = *this - 1; return result;}
BigInt operator+= (BigInt other) {return *(this) = *(this) + other;}
BigInt operator-= (BigInt other) {return *(this) = *(this) - other;}
BigInt operator*= (BigInt other){return *(this) = *(this) * other;}
BigInt operator/= (BigInt other){return *(this) = *(this) / other;}
BigInt operator%= (BigInt other){return *(this) = *(this) % other;}
BigInt operator&= (BigInt other){return *(this) = *(this) & other;}
BigInt operator|= (BigInt other){return *(this) = *(this) | other;}
BigInt operator^= (BigInt other){return *(this) = *(this) ^ other;}
BigInt operator<<= (BigInt other){return *(this) = *(this) << other;}
BigInt operator>>= (BigInt other){return *(this) = *(this) >> other;}
int operator[] (BigInt &value) {
return (int) value;
}
explicit operator bool() {
return *this != 0;
}
explicit operator int() {
int result = 0;
for (auto i : digits)
result = result * 10 + i;
return result;
}
friend bool operator !(const BigInt &other) {
return other == 0;
}
friend std::string to_string(const BigInt &value) {
std::string result;
if (value.negative)
result += '-';
for (int i = value.digits.size() - 1; i >= 0; i--)
result += value.digits[i] + '0';
return result;
}
friend BigInt abs(const BigInt &value) {
BigInt result = value;
result.negative = false;
return result;
}
void trim() {
while (digits.size() > 1 && digits.back() == 0)
digits.pop_back();
if (digits.size() == 1 && digits.back() == 0)
negative = false;
}
friend std::istream& operator>> (std::istream& in, BigInt &value){
std::string s; in >> s;
value = BigInt(s);
return in;
}
friend std::ostream& operator<< (std::ostream& out, const BigInt &value){
auto digits = value.digits;
if (value.negative)
out << "-";
for (auto it = digits.rbegin(); it != digits.rend(); it++)
out << *it;
return out;
}
};