24 std::vector<std::uint8_t> digits;
25 bool isNegative =
false;
28 void removeLeadingZeros() {
29 while (digits.size() > 1 && digits.back() == 0) {
32 if (digits.size() == 1 && digits[0] == 0) {
37 [[nodiscard]]
bool _isAbsoluteGreaterOrEqual(
const BigInteger &other)
const {
38 if (digits.size() != other.digits.size()) {
39 return digits.size() > other.digits.size();
42 for (
int i =
static_cast<int>(digits.size()) - 1; i >= 0; --i) {
43 if (digits[i] != other.digits[i]) {
44 return digits[i] > other.digits[i];
51#pragma region private constructors
55 BigInteger(
bool isNegative,
const std::vector<std::uint8_t> &digits)
56 : digits(digits), isNegative(isNegative) {
61#pragma region add&subtract
65 result.digits.clear();
67 size_t maxLength = std::max(digits.size(), other.digits.size());
70 for (
size_t i = 0; i < maxLength || carry; ++i) {
73 if (i < digits.size()) {
74 digitSum += digits[i];
76 if (i < other.digits.size()) {
77 digitSum += other.digits[i];
80 result.digits.push_back(digitSum % 10);
81 carry = digitSum / 10;
89 result.digits.clear();
92 for (
size_t i = 0; i < digits.size(); ++i) {
93 int digitSub = digits[i] - borrow - (i < other.digits.size() ? other.digits[i] : 0);
101 result.digits.push_back(digitSub);
104 result.removeLeadingZeros();
112#pragma region conversion
124 if (!number.empty() && number[0] ==
'-') {
125 result.isNegative =
true;
129 for (
size_t i = number.size(); i > start; --i) {
130 char c = number[i - 1];
131 if (c <
'0' || c >
'9') {
132 throw std::invalid_argument(
"Invalid character in number string.");
134 result.digits.push_back(c -
'0');
136 result.removeLeadingZeros();
146 template<std::
integral T>
148 if (number == std::numeric_limits<T>::min()) {
154 result.isNegative =
true;
159 result.digits.push_back(number % 10);
161 }
while (number > 0);
171 if (digits.empty()) {
180 str.reserve(digits.size() + str.size());
181 for (
unsigned char digit: std::ranges::reverse_view(digits)) {
182 str +=
static_cast<char>(
'0' + digit);
197 template<std::
integral T>
198 std::optional<T>
to()
const {
202 if constexpr (!std::is_signed_v<T>) {
208 for (
size_t i = 0; i < digits.size(); ++i) {
209 T digitValue =
static_cast<T
>(digits[i]);
212 T tempResult = result + digitValue * multiplier;
213 if (tempResult < result) {
219 if (i < digits.size() - 1) {
220 if (std::numeric_limits<T>::max() / 10 < multiplier) {
227 if constexpr (std::is_signed_v<T>) {
229 if (result == 0 || result > std::numeric_limits<T>::max()) {
241#pragma region singletons
276 template<std::
integral T>
279 if constexpr (std::is_signed_v<T>) {
280 T number = std::numeric_limits<T>::min();
282 result.isNegative =
true;
285 if (number == std::numeric_limits<T>::min()) {
286 result.digits.push_back(-(number % 10));
292 result.digits.push_back(number % 10);
311 template<std::
integral T>
314 T number = std::numeric_limits<T>::max();
316 result.isNegative =
false;
319 result.digits.push_back(number % 10);
333 if (digits.size() == 1 && digits[0] == 0) {
337 isNegative = !isNegative;
347 result.isNegative =
false;
360#pragma region arithmetic
370 if (isNegative == other.isNegative) {
371 result = _add(other);
372 result.isNegative = isNegative;
375 if (_isAbsoluteGreaterOrEqual(other)) {
376 result = _subtract(other);
377 result.isNegative = isNegative;
379 result = other._subtract(*
this);
380 result.isNegative = other.isNegative;
384 result.removeLeadingZeros();
385 if (result.digits.size() == 1 && result.digits[0] == 0) {
386 result.isNegative =
false;
399 negatedOther.isNegative = !other.isNegative;
400 return *
this + negatedOther;
424 size_t totalLength = digits.size() + other.digits.size();
426 result.digits.resize(totalLength, 0);
429 for (
size_t i = 0; i < digits.size(); ++i) {
431 for (
size_t j = 0; j < other.digits.size() || carry; ++j) {
432 int product = carry + result.digits[i + j];
433 if (j < other.digits.size()) {
434 product += digits[i] * other.digits[j];
436 result.digits[i + j] = product % 10;
437 carry = product / 10;
441 result.removeLeadingZeros();
442 result.isNegative = isNegative != other.isNegative;
466 throw std::runtime_error(
"Division by zero");
473 quotient.digits.resize(dividend.digits.size(), 0);
475 for (
int i =
static_cast<int>(dividend.digits.size()) - 1; i >= 0; --i) {
478 while (current >= divisor) {
479 current = current - divisor;
482 quotient.digits[i] = count;
485 quotient.removeLeadingZeros();
489 quotient.isNegative =
false;
492 quotient.isNegative = isNegative != other.isNegative;
512 *
this = *
this + other;
529 *
this = *
this - other;
541 *
this = *
this * other;
552 *
this = *
this / other;
570 throw std::runtime_error(
"Modulo by zero");
599 throw std::runtime_error(
"Modulo by zero");
606 return std::make_pair(quotient, remainder);
616 if (a.isNegative && !b.isNegative)
return b;
617 if (!a.isNegative && b.isNegative)
return a;
620 if (a._isAbsoluteGreaterOrEqual(b))
621 return a.isNegative ? b : a;
622 return a.isNegative ? a : b;
632 if (a.isNegative && !b.isNegative)
return a;
633 if (!a.isNegative && b.isNegative)
return b;
636 if (a._isAbsoluteGreaterOrEqual(b))
637 return a.isNegative ? a : b;
638 return a.isNegative ? b : a;
641#pragma region increment & decrement
672#pragma region comparators
676 return isNegative == other.isNegative && digits == other.digits;
681 return !(*
this == other);
686 if (isNegative != other.isNegative) {
690 if (digits.size() != other.digits.size()) {
691 return isNegative ? digits.size() > other.digits.size() : digits.size() < other.digits.size();
694 for (
int i =
static_cast<int>(digits.size()) - 1; i >= 0; --i) {
695 if (digits[i] != other.digits[i]) {
696 return isNegative ? digits[i] > other.digits[i] : digits[i] < other.digits[i];
705 return *
this == other || *
this < other;
710 return !(*
this <= other);
715 return !(*
this < other);
766 return lcmValue.
abs();
778 for (
unsigned int i = 2; i <= n; ++i) {
802 result = result * base;
819 if (number.isNegative) {
820 throw std::runtime_error(
"Square root of a negative number is not defined.");
823 if (number ==
zero() || number ==
one()) {
831 while (low <= high) {
835 if (square == number) {
837 }
else if (square < number) {
858 throw std::out_of_range(
"log2(0) is undefined");
860 if (number.isNegative) {
861 throw std::out_of_range(
"log2(negative) is not allowed");
882 throw std::out_of_range(
"log10(0) is undefined");
884 if (number.isNegative) {
885 throw std::out_of_range(
"log10(negative) is not allowed");
901 if (*
this ==
zero())
return;
902 digits.insert(digits.begin(), power, 0);
903 removeLeadingZeros();
915 if (power >= digits.size()) {
922 digits.erase(digits.begin(), digits.begin() +
static_cast<int>(power));
924 removeLeadingZeros();
Implements a class for representing and manipulating large integers beyond the native integer range.
Definition big_integer.hpp:22
bool operator>=(const BigInteger &other) const
Definition big_integer.hpp:714
std::optional< T > to() const
Definition big_integer.hpp:198
static BigInteger lcm(const BigInteger &a, const BigInteger &b)
Definition big_integer.hpp:757
BigInteger & operator-=(const BigInteger &other)
Definition big_integer.hpp:527
bool operator>(const BigInteger &other) const
Definition big_integer.hpp:709
BigInteger operator%(const BigInteger &other) const
Definition big_integer.hpp:568
bool operator<(const BigInteger &other) const
Definition big_integer.hpp:685
bool operator==(const BigInteger &other) const
Definition big_integer.hpp:675
static const BigInteger & getMaxValueInstance()
Definition big_integer.hpp:312
BigInteger & operator+=(const BigInteger &other)
Definition big_integer.hpp:510
static BigInteger factorial(unsigned int n)
Definition big_integer.hpp:775
std::string to_string() const
Definition big_integer.hpp:170
BigInteger operator+(const BigInteger &other) const
Definition big_integer.hpp:367
BigInteger operator--(int)
Definition big_integer.hpp:663
BigInteger operator++(int)
Definition big_integer.hpp:650
BigInteger operator/(const BigInteger &other) const
Definition big_integer.hpp:464
static const BigInteger & getMinValueInstance()
Definition big_integer.hpp:277
BigInteger & operator/=(const BigInteger &other)
Definition big_integer.hpp:551
static BigInteger log2(const BigInteger &number)
Definition big_integer.hpp:856
static BigInteger min(const BigInteger &a, const BigInteger &b)
Definition big_integer.hpp:631
bool operator<=(const BigInteger &other) const
Definition big_integer.hpp:704
static BigInteger log10(const BigInteger &number)
Definition big_integer.hpp:880
BigInteger operator*(const BigInteger &other) const
Definition big_integer.hpp:418
void negate()
Definition big_integer.hpp:332
BigInteger operator-(const BigInteger &other) const
Definition big_integer.hpp:397
BigInteger & operator++()
Definition big_integer.hpp:644
static BigInteger gcd(const BigInteger &a, const BigInteger &b)
Definition big_integer.hpp:731
void divideByPowerOfTen(std::size_t power)
Definition big_integer.hpp:914
static BigInteger sqrt(const BigInteger &number)
Definition big_integer.hpp:818
static const BigInteger & one()
Definition big_integer.hpp:257
static BigInteger parse(const std::string &number)
Definition big_integer.hpp:120
BigInteger operator-() const
Definition big_integer.hpp:353
bool operator!=(const BigInteger &other) const
Definition big_integer.hpp:680
BigInteger & operator*=(const BigInteger &other)
Definition big_integer.hpp:540
static BigInteger max(const BigInteger &a, const BigInteger &b)
Definition big_integer.hpp:615
BigInteger abs() const
Definition big_integer.hpp:345
static const BigInteger & two()
Definition big_integer.hpp:266
static BigInteger pow(const BigInteger &a, unsigned int n)
Definition big_integer.hpp:792
std::pair< BigInteger, BigInteger > divmod(const BigInteger &other) const
Definition big_integer.hpp:597
BigInteger & operator--()
Definition big_integer.hpp:657
void multiplyByPowerOfTen(std::size_t power)
Definition big_integer.hpp:900
static BigInteger from_integer(T number)
Definition big_integer.hpp:147
static const BigInteger & zero()
Definition big_integer.hpp:248
Definition big_integer.hpp:14