Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

PROJECT: High-precision arithmetic is required in many different fields of study

ID: 3754150 • Letter: P

Question

PROJECT:

High-precision arithmetic is required in many different fields of study. One area where it is used is public-key cryptography, where information is encoded and decoded using integers more than 100 digits long. In the interest of being able to handle such long integers as these, this project asks you to implement a class that can read in, store, print, and add very long positive integers. Provide a complete program that includes a VeryLongInt class that contains one data member - a char vector named digits. Why char? Because a char requires less storage space than the standard numeric types - only 8 bits for a char as compared to 32 bits for an int. And saving space can be important for programs that use lots of very long integers.

Your VeryLongInt class should contain:

A 0-parameter constructor that stores a default value of '0' in the vector.

A 1-parameter constructor that stores the passed in string parameter, numStr, in the vector. Store each of numStr's char digits as an element in the digits vector. If any of numStr's char "digits" is not a digit, print an error message and store a default value of '0' in the vector.

An overloaded >> input operator that stores the user-entered value in the vector. Store each char from the user-entered value as an element in the digits vector. If any of the user-entered char "digits" is not a digit, print an error message and store a default value of '0' in the vector.

An overloaded << output operator that prints the contents of the vector.

An overloaded + operator that adds two VeryLongInt objects and returns the sum in the form of a new VeryLongInt object.

At least one appropriate helper member function.

Since this is a non-trivial program (my implementation is four total pages of code including the given driver

file and the extra credit), you are required to break it up into separate files in the standard manner. Use these

files:

veryLongInt.h: for the VeryLongInt class definition

veryLongInt.cpp: for member function definitions and overloaded << and >> friend functions.

veryLongIntDriver.cpp: for driving the VeryLongInt class

Explanation / Answer

test1.cc

#include "very_long_int.h"
#include <assert.h>
using namespace std;
void test_0(){
   short a = 1;
   int b = 1;
   long c = 1;
   long long d = 1L;
   unsigned short e = 1;
   unsigned int f = 1;
   unsigned long g = 1;
   unsigned long long h = 1L;
   assert(VeryLongInt(a) == 1);
   assert(VeryLongInt(1ULL) == 1);
   assert(VeryLongInt(1UL) == 1);
   assert(VeryLongInt(1LL) == 1);
   assert(VeryLongInt(1U) == 1);
   assert(VeryLongInt(b) == 1);
   assert(VeryLongInt(c) == 1);
   assert(VeryLongInt(d) == 1);
   assert(VeryLongInt(e) == 1);
   assert(VeryLongInt(f) == 1);
   assert(VeryLongInt(g) == 1);
   assert(VeryLongInt(h) == 1);
   unsigned char i = 1;
   signed char j = 1;
   assert(VeryLongInt(i) == 1);
   assert(VeryLongInt(j) == 1);
   size_t k = 1;
   assert(VeryLongInt(k) == 1);
   VeryLongInt ver = 1;
   ver <<= a;
   ver <<= b;
   ver <<= c;
   ver <<= d;
   ver <<= e;
   ver <<= f;
   ver <<= g;
   ver <<= h;
   ver <<= i;
   ver <<= j;
   ver <<= k;
  
   ver >>= a;
   ver >>= b;
   ver >>= c;
   ver >>= d;
   ver >>= e;
   ver >>= f;
   ver >>= g;
   ver >>= h;
   ver >>= i;
   ver >>= j;
   ver >>= k;      
}
void test_1(){
   VeryLongInt a(4);
   assert( a.isValid() );
  
   VeryLongInt b(2);
   assert( a != b);
   a = 2;
   assert( a == b);
  
   VeryLongInt O;
   assert( O == 0 );
   assert( a.isValid() );
   a -= 5;
   assert(not a.isValid() );
  
   char c[3]; c[0] = '4'; c[1] = '2'; c[2] = '';
   assert(VeryLongInt("42") == 42);
   assert(VeryLongInt(c) == 42);
   assert(VeryLongInt( string("42") ) == 42);
   //a += "42"; //Ma si nie kompilowa :                              OK.
   // a = string("42"); // Ma si nie kompilowa:                      OK
   //VeryLongInt q('4'); // Ma si nie kompilowa:                     OK
  
  
}

void test_2(){
   VeryLongInt a(13);
   VeryLongInt b(4);

   VeryLongInt c(1);
   VeryLongInt d(4);

   assert( c < d );

   cout << ((a - b) - b) - b << " == 1 ";
   assert ( ((a - b) - b) - b == 1 );
   assert ( ((a - b) - b) - b > 0 );
   assert ( ((a - b) - b) - b < b );

   VeryLongInt e(13);
   VeryLongInt f(4);

   e -= f;
   assert( e == 9 );
   e -= f;
   assert( e == 5 );
   e -= f;
   assert( e == 1 );

   assert( e < f );

   assert( a + b == 17);
   assert( a - b == 9);
   assert( a * b == 52);
   assert( a / b == 3);
   assert( a % b == 1);

   assert( a << 1 == 26);
   assert( a >> 1 == 6);
   a += b;
   assert(a == 17);
   assert(b == 4);
   a -= b;
   assert(a == 13);
   assert(b == 4);
   a *= b;
   assert(a == 52);
   assert(b == 4);
   a /= b;
   assert(a == 13);
   assert(b == 4);
   a /= b;
   assert(a == 3);
   a %= 2;

   assert(a == 1);
   a >>= 1;
   assert(a == 0);
   a >>= 1;
   assert(a == 0);
   a <<= 1;
   assert(a == 0);
   a += 3;
   a <<= 2;
   assert(a == 12);
  
}

void test_3(){
   VeryLongInt a;
   a = 4;
   assert(a);
   a = 0;
   assert( not a);
   a -= 3;
   assert( not a);
   //a = true; // Ma si nie kompilowa:                               OK
}

void test_4(){
   long long int x = 100000000000000000L;
   VeryLongInt a(x);
   assert( a == x);
   a += x;
   assert ( a == 2L * x);
   a = a + a + a + a;
   assert( a == 8L * x);
   a = 0;
   for( int i = 0; i < 10000 ; i++)
       a += x;
  
   for( int i = 0; i < 10000 ; i++)
       a -= x;
  
   assert( a == 0);
  
   long long int y = 4294967295L;
   a = y;
   a += 1;
   assert( a == y + 1L);
   a -= 2;
   assert( a == y - 1L);
   a = y; a += y;
   assert( a == 2L * y);
   a -= y + 1L;
   assert( a == y -1L );
}

void test_5(){
   VeryLongInt a, b;
   a = 2;
   a *= 2;
   assert( a == 4);
   long long int x = 1000000L;
   a = x;
   a *= x;
   assert( a == x *x);
   a *= x;
   assert( a == x *x * x);
  
}

void test_6(){
   VeryLongInt a("121212121212121212121212121212");
   VeryLongInt b("100000000000000000000000000000000");
   VeryLongInt c("121212121212121212121212121212"
                  "00000000000000000000000000000000");
   assert(a * b == c);
  
}

void test_7(){
   VeryLongInt a, b;
   a = 10000000000000000L;
   b = 100000000000000L;
   assert( a / b == 100);
   a = 1;
   a <<= 32;
   assert(a == 1L <<32);
   a *= 1L<<32;
   a >>= 44;
   assert( a == 1 << 20);
  
}
void test_8(){
   VeryLongInt a, b;
   a = 1;
   a <<= 64;
   cout << a << " / 2 = " << a / 2 << endl;
}

// Proste testy na podstawowe operatory 2 argumentowe, 10x:
void test_100(){
   VeryLongInt x = 1;
   assert(x == 1);
}

void test_101(){
   VeryLongInt x = 2;
   VeryLongInt y = 3;
   assert(x + y == 5);
   assert(y - x == 1);
}

void test_102(){
   VeryLongInt x = 4;
   VeryLongInt y = 5;
   assert(x * y == 20);
}

void test_103(){
   VeryLongInt x = 40;
   VeryLongInt y = 5;
   assert(x / y == 8);
}

void test_104(){
   VeryLongInt x = 14;
   VeryLongInt y = 5;
   assert(x % y == 4);
}

// Proste testy na operatory jedno argumentowe 11x:
void test_110(){
   VeryLongInt x = 1;
   VeryLongInt y = 0;
   x += y;
   assert(x == 1);
}

void test_111(){
   VeryLongInt x = 2;
   VeryLongInt y = 3;
   x += y;
   assert(x == 5);
   assert(y == 3);
  
   x -= y;
   assert(x == 2);
   assert(y == 3);
}

void test_112(){
   VeryLongInt x = 4;
   VeryLongInt y = 5;
   x *= y;
   assert(x == 20);
   assert(y == 5);
}

void test_113(){
   VeryLongInt x = 40;
   VeryLongInt y = 5;
   x /= y;
   assert(x == 8);
   assert(y == 5);
}

void test_114(){
   VeryLongInt x = 14;
   VeryLongInt y = 5;
   x %= y;
   assert(x == 4);
   assert(y == 5);
}

void test_115(){
   VeryLongInt x = 14;
   int y = 1;
   x >>= y;
   assert(x == 7);
   assert(y == 1);
}

void test_116(){
   VeryLongInt x = 6;
   int y = 3;
   x <<= y;
   assert(x == 48);
   assert(y == 3);
}

// Proste testy na operatory porównujce 12x:
void test_120(){
   VeryLongInt x = 1;
   VeryLongInt y = 2;
   assert(x < y);
}

void test_121(){
   VeryLongInt x = 1;
   VeryLongInt y = 2;
   assert(x <= y);
}

void test_122(){
   VeryLongInt x = 9;
   VeryLongInt y = 4;
   assert(x > y);
}

void test_123(){
   VeryLongInt x = 9;
   VeryLongInt y = 4;
   assert(x >= y);
}

void test_124(){
   VeryLongInt x = 1;
   VeryLongInt y = 1;
   assert(x == y);
}

void test_125(){
   VeryLongInt x = 1;
   VeryLongInt y = 2;
   assert(x != y);
}

void test_126(){
   VeryLongInt x = 1;
   VeryLongInt y = 1;
   assert(x <= y);
}

void test_127(){
   VeryLongInt x = 1;
   VeryLongInt y = 1;
   assert(x >= y);
}

void test_128(){
   VeryLongInt x = 1;
   VeryLongInt y = 1;
   assert(not(x < y));
}

void test_129(){
   VeryLongInt x = 8;
   VeryLongInt y = 2;
   assert(not(y >= x));
}


// Testy podane w treci zadania 100xy:

void test_10000(){
   VeryLongInt x = 1;
   x /= 0;
   assert(!x.isValid());
}

void test_10001(){
   VeryLongInt x = 100;
   x -= 101;
   assert(!x.isValid());
}

void test_10002(){
   VeryLongInt x = NaN();
   assert(!x.isValid());
}

void test_10003(){
   VeryLongInt x = 23;
   VeryLongInt y = x;
   assert(x == y);
}

void test_10004(){
   VeryLongInt x = 23;
   VeryLongInt y = 32;
   x = y;
   assert(x == y);
}

void test_10005(){
   VeryLongInt x = 23;
   VeryLongInt y = 32;
   assert(y > x);
}

void test_10006(){
   VeryLongInt x = 23;
   VeryLongInt y = 32;
   assert(y >= x);
}

void test_10007(){
   VeryLongInt x = 10;
   if (x)
       assert(1);
   else
       assert(0);
}

void test_10008(){
   VeryLongInt x = 1;
   x <<= 1;
   assert(2 == x);
}

void test_10009(){
   VeryLongInt x = 8;
   x >>= 2;
   assert(2 == x);
}

void test_10010(){
   VeryLongInt x = 1;
   x <<= 123;
   x >>= 120;
   assert(8 == x);
}

void test_10011(){
   VeryLongInt x = 1;
   for (int i = 1; i <= 100; ++i)
       x *= 2;
   assert(x % 3 == 1);
}

void test_10012(){
   VeryLongInt x = Zero() ;
   assert(x == 0);
}

void test_10013(){
   const int N = 100;
   VeryLongInt x = 1;
   for (int i = 1; i < N; ++i)
       x *= 2;
   assert(x.numberOfBinaryDigits() == N);
}

void test_10014(){
   VeryLongInt x("1234567890123456789012345678901234567890");
   VeryLongInt z = x;
   VeryLongInt y("777777777777777777777777777777777777777");
   x = x + y;
   x -= y;
   assert(x == z);
}

void test_10015(){
   VeryLongInt x(string("12345678"));
   VeryLongInt y(12345678U);
   assert(x == y);
}

void test_10016(){
   VeryLongInt x("12345678901234567890");
   VeryLongInt y(12345678901234567890UL);
   assert(x == y);
}

void test_10017(){  
   VeryLongInt x("1234567890123456789012345678901234567890");
   VeryLongInt y("1204567890123456789012345678901234567890");
   VeryLongInt z( "30000000000000000000000000000000000000");
   assert(z == x - y);
}

void test_10018(){
   VeryLongInt x("10000000000");
   VeryLongInt y("100000000000");
   VeryLongInt z("1000000000000000000000");
   assert(z == x * y);
}

void test_10019(){
   const int N = 1000;
   VeryLongInt x = 1;
    for (int i = 2; i <= N; ++i) {
   
       x *= i;
    }

   for (int i = 2; i <= N; ++i) {
       cout << "BLE" << endl;  
       x /= i;
       cout << "BLE2" << endl;
      
}

   assert(x == 1);
}

void test_10020(){
   assert(Zero().numberOfBinaryDigits() == 1);
   assert(NaN().numberOfBinaryDigits() == 0);
}

void test_200(){
  
   VeryLongInt a("4545484498498554584512549849849184465592315879466114848794312158197973724518419879796734315118198797994613112515487979791112223334497846531277445774513245754479835614854978846461329774559849846");
   VeryLongInt b("121212459999949454524548489844642444849891664648484989776885489797646545487979434343448877989986535345579879899");
   assert(a + b ==
       VeryLongInt("4545484498498554584512549849849184465592315879466114848794312158197973724518419879917946775118148252519161602360130424641003887982982836308162935572159791242459269958303856836447865120139729745")
       );
   assert( b + a == a + b);
   assert(a * b ==
       VeryLongInt("550969357954646353957909989532470222552703175037625207389639357479776013775041240813811148518858798585392408352938948150839849067703590011655696882854642367908906119224323305473838227260010292455759540333951935781058769632192176049392503116960336689023119071332600680706047968451745802049265368153645554")
       );
   assert(b * a == a * b);
   assert(a / b ==
       VeryLongInt("37500142299730985139931893469870855085222241132506829985590217560218270238880726424")
       );
   assert(b / a == 0);
   assert(a % b ==
       VeryLongInt("81497443140207043543330620739240219519680708432265694577773198146114239881890109775165870689833011982764098670")
       );
   assert(b % a == b
       );
}

void test_wypisywania(){
   VeryLongInt a = 12345;
   cout << a << " = 12345" << endl;
   VeryLongInt x(12345678901234L);
   cout << x << " = 12345678901234" << endl;
}


int main(){
  
  

   test_wypisywania();

  
   test_0();
   test_1();
   test_2();
   test_3();
   test_4();
   test_5();
   test_6();
   test_7();  
   test_8();
  
  
   // Bardzo proste testy:
   test_100();
   test_101();
   test_102();
   test_103();
   test_104();
  
   test_110();
   test_111();
   test_112();
   test_113();
   test_114();
   test_115();
   test_116();
  
   test_120();
   test_121();
   test_122();
   test_123();
   test_124();
   test_125();
   test_126();
   test_127();
   test_128();
   test_129();
  
  
   // Testy Poprawnociowe:
   test_200();
  
   // Testy z treci zadania:
   test_10000();
   test_10001();
   test_10002();
   test_10003();
   test_10004();
   test_10005();
   test_10006();
   test_10007();
   test_10008();
   test_10009();

   test_10010();
   test_10011();
   test_10012();
   test_10013();
   test_10014();
   test_10015();
   test_10016();
   test_10017();
   test_10018();
   test_10020();
    cout << "Przed testem z silnia." << endl;
   //test_10019();
    cout << "Test z silnia zakonczony. " << endl;  
  

}


very_long_int.cc

#include "very_long_int.h"
using namespace std;

static const uint64_t BASE = 1LL << 32;

VeryLongInt::VeryLongInt(const VeryLongInt &x) : isNaN(x.isNaN), data(x.data) {
}

VeryLongInt::VeryLongInt(uint32_t x): isNaN(false) {
data.clear();
data.push_back(x);
}

VeryLongInt::VeryLongInt(uint64_t x): isNaN(false) {
data.clear();
uint32_t tempNumber;
tempNumber = (uint32_t) (x % BASE);
data.push_back(tempNumber);
tempNumber = (uint32_t) (x >> 32);
if (tempNumber > 0) data.push_back(tempNumber);
}

VeryLongInt::VeryLongInt(const string &x) {
VeryLongInt currentResult;
for (char c : x) {
    currentResult = (currentResult * 10) + (int)(c - '0');
    if (c < '0' || c > '9')
      currentResult.isNaN = true;
}
*this = currentResult;
}

VeryLongInt::VeryLongInt(const char *x) {
*this = VeryLongInt(string(x));
}

bool VeryLongInt::isValid() const {
return not isNaN;
}

void VeryLongInt::correct_invariants() {
if (data.size() == 0)
    data.push_back(0);
while (data[data.size() - 1] == 0 && data.size() > 1)
    data.pop_back();
}

VeryLongInt::operator bool() const {
if (not isValid())
    return false;
if (*this == 0)
    return false;
return true;
}

size_t VeryLongInt::numberOfBinaryDigits() const {
if (not isValid())
    return 0;
if (*this == 0)
    return 1;
size_t result = (data.size() - 1) * 32;
uint32_t tmp = data[data.size() - 1];
while (tmp > 0) {
    tmp >>= 1;
    result++;
}
return result;
}

VeryLongInt & VeryLongInt::operator=(const VeryLongInt &x) {
isNaN = x.isNaN;
data = x.data;
return *this;
}

VeryLongInt & VeryLongInt::operator+=(const VeryLongInt &x) {
if (isNaN || x.isNaN)
    isNaN = true;
else {
    uint64_t tmp = 0L;
    while(data.size() < x.data.size())
      data.push_back(0);
    data.push_back(0);
  
    for (size_t i = 0; i < x.data.size(); i++) {
      tmp += (uint64_t) x.data[i] + (uint64_t) data[i];
      data[i] = (uint32_t) (tmp % BASE);
      tmp /= BASE;
    }
    for (size_t i = x.data.size(); tmp > 0L; i++) {
      tmp += data[i];
      data[i] = (uint32_t) (tmp % BASE);
      tmp /= BASE;
    }
    correct_invariants();
}
return *this;
}

VeryLongInt & VeryLongInt::operator-=(const VeryLongInt &x) {
if (isNaN || x.isNaN || data.size() < x.data.size())
    isNaN = true;
else {
    uint64_t tmp = BASE;
    for (size_t i = 0; i < x.data.size(); i++) {
      tmp += (uint64_t) data[i] - (uint64_t) x.data[i];
      data[i] = (uint32_t) (tmp % BASE);
      if (tmp < BASE) {
        tmp = BASE - 1L;
      } else {
        tmp = BASE;
      }
    }
    if (tmp < BASE) {
      if (data.size() > x.data.size()) {
        data[x.data.size()] -= 1;
      } else {
        isNaN = true;
      }
    }
    correct_invariants();
}
return *this;
}

void VeryLongInt::multiplyByDigitAndShift(
    VeryLongInt &result,
    uint32_t digitArg,
    uint32_t shift) const {
result.data = vector <uint32_t>();
uint64_t currentTempResult = 0;
uint32_t currentRest = 0;
uint32_t sizeOfThisData = data.size();
for (uint32_t i = 0; i < shift; ++i)
    result.data.push_back(0);
for (uint32_t i = 0; i < sizeOfThisData; ++i) {
    currentTempResult = (uint64_t)digitArg * (uint64_t)data[i] + (uint64_t)currentRest;
    result.data.push_back(currentTempResult % BASE);
    currentRest = currentTempResult / BASE;
}
if (currentRest > 0)
    result.data.push_back(currentRest);
}

VeryLongInt & VeryLongInt::operator*= (const VeryLongInt &x) {
if (isNaN || x.isNaN)
    isNaN = true;
else {
    VeryLongInt currentResult;
    VeryLongInt currentTemp ;
    for (size_t i = 0; i < data.size(); ++i) {
      x.multiplyByDigitAndShift(
          currentTemp,
          data[i],
          i);
      currentResult += currentTemp;
    }
    *this = currentResult;
}
correct_invariants();
return *this;
}

VeryLongInt & VeryLongInt::operator/=(const VeryLongInt &x) {
if (isNaN || x.isNaN || x == 0)
    isNaN = true;
else {
    const uint32_t lengthOfX = x.data.size();
    const uint32_t lengthOfThis = data.size();
    VeryLongInt result;
    if (lengthOfThis < lengthOfX)
      *this = result;
    else {
      VeryLongInt helperNumberDividing(x);
      VeryLongInt helperNumberDivided(*this);
      int32_t nrOfZerosAddedToHelper = lengthOfThis - lengthOfX;
      if (nrOfZerosAddedToHelper > 0) {
        vector <uint32_t> zerosToInsert(nrOfZerosAddedToHelper, 0);
        helperNumberDividing.data.insert(
            helperNumberDividing.data.begin(),
            zerosToInsert.begin(),
            zerosToInsert.end());
      }
      while (nrOfZerosAddedToHelper >= 0) {
        uint64_t base2Counter = 1;
        int32_t base2Index = 0;
        vector <VeryLongInt> base2Vector;
        VeryLongInt temp;
        base2Vector.push_back(helperNumberDividing);
        while ((temp = base2Vector[base2Index] * 2) <= helperNumberDivided) {
          base2Counter *= 2;
          base2Index += 1;
          base2Vector.push_back(temp);
        }
        while (base2Index >= 0) {
          while (base2Vector[base2Index] <= helperNumberDivided) {
            helperNumberDivided -= base2Vector[base2Index];
            result += base2Counter;
          }
          base2Counter /= 2;
          base2Index -= 1;
        }
        --nrOfZerosAddedToHelper;
        helperNumberDividing.data.erase(
            helperNumberDividing.data.begin());
        if (result > 0 && nrOfZerosAddedToHelper >= 0)
          result.data.insert(
              result.data.begin(),
              0);
      }
      *this = result;
    }
}
correct_invariants();
return *this;
}

VeryLongInt & VeryLongInt::operator%=(const VeryLongInt &x) {
if (isNaN || x.isNaN || x == 0) {
    isNaN = true;
} else {
VeryLongInt k = (*this / x);
*this -= k * x;
}
return *this;
}

VeryLongInt & VeryLongInt::operator<<=(uint64_t x) {
if (not isNaN) {
    uint64_t temp = x / 32;
    if (temp > 0) {
    vector<uint32_t> helperVector = data;
    size_t index = 0;
    while (index < temp) {
      data.push_back(0);
      data[index++] = 0;
    }
    for (uint32_t var : helperVector)
      data[index++] = var;
}
temp = x - temp * 32;

    *this = *this * (1 << temp);
}
return *this;
}
VeryLongInt & VeryLongInt::operator>>=(uint64_t x) {
   if (not isNaN) {
    uint64_t temp = x / 32;
    if (temp > 0) {
    for (size_t index= 0; index + temp < data.size() ; index++)
      data[index] = data[index + temp];
    for (size_t index= 0; index < temp ; index++)
      data.pop_back();
}
temp = x - temp * 32;

    *this = *this / (1 << temp);
}
return *this;
}

VeryLongInt &operator+(const VeryLongInt &a, const VeryLongInt &b) {
VeryLongInt * result;
result = new VeryLongInt(a);
*result += b;
return *result;
}

VeryLongInt &operator-(const VeryLongInt &a, const VeryLongInt &b) {
VeryLongInt * result;
result = new VeryLongInt(a);
*result -= b;
return *result;
}

VeryLongInt &operator*(const VeryLongInt &a, const VeryLongInt &b) {
VeryLongInt * result;
result = new VeryLongInt(a);
*result *= b;
return *result;
}

VeryLongInt &operator/(const VeryLongInt &a, const VeryLongInt &b) {
VeryLongInt * result;
result = new VeryLongInt(a);
*result /= b;
return *result;
}

VeryLongInt &operator%(const VeryLongInt &a, const VeryLongInt &b) {
VeryLongInt * result;
result = new VeryLongInt(a);
*result %= b;
return *result;
}

VeryLongInt &operator<<(const VeryLongInt &a, unsigned int b) {
VeryLongInt * result;
result = new VeryLongInt(a);
*result <<= b;
return *result;
}

VeryLongInt &operator>>(const VeryLongInt &a, unsigned int b) {
VeryLongInt * result;
result = new VeryLongInt(a);
*result >>= b;
return *result;
}

bool operator==(const VeryLongInt &a, const VeryLongInt &b) {
if (not (a.isValid() && b.isValid()))
    return false;
return ((a - b).isValid() && (b - a).isValid());
}

bool operator!=(const VeryLongInt &a, const VeryLongInt &b) {
if (not (a.isValid() && b.isValid()))
    return false;
return not (a == b);
}

bool operator<(const VeryLongInt &a, const VeryLongInt &b) {
if (not (a.isValid() && b.isValid()))
    return false;
return ((b - a).isValid() && not (a - b).isValid());
}

bool operator<=(const VeryLongInt &a, const VeryLongInt &b) {
if (not (a.isValid() && b.isValid()))
    return false;
return (b - a).isValid();
}

bool operator>(const VeryLongInt &a, const VeryLongInt &b) {
if (not (a.isValid() && b.isValid()))
    return false;
return not (a <= b);
}

bool operator>=(const VeryLongInt &a, const VeryLongInt &b) {
if (not (a.isValid() && b.isValid()))
    return false;
return not (a < b);
}

ostream & operator<<(ostream & outputStream, const VeryLongInt & x) {
if (not x.isValid())
    outputStream << "NaN";
else if (x <= 9)
    outputStream << x.data[0];
else {
    VeryLongInt temp = x;
    stack<int> outputStack;
    while (temp > 0) {
      outputStack.push((temp % 10).data[0]);
      temp /= 10;
    }
    while (not outputStack.empty()) {
      outputStream << outputStack.top();
      outputStack.pop();
    }
}
return outputStream;
}

VeryLongInt const &Zero() {
const static VeryLongInt global_zero = VeryLongInt();
return global_zero;
}

VeryLongInt const &NaN() {
const static VeryLongInt global_NaN = VeryLongInt(0) - VeryLongInt(1);
return global_NaN;
}


very_long_int.h

#ifndef VERY_LONG_INT_H
#define VERY_LONG_INT_H
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stack>

class VeryLongInt{
private:
    bool isNaN;
    std::vector<uint32_t> data;
    int date;
    void correct_invariants();
    void multiplyByDigitAndShift(VeryLongInt &, uint32_t, uint32_t) const;
  
public:
    VeryLongInt(const VeryLongInt &);
    VeryLongInt(uint32_t arg = 0U);
    VeryLongInt(uint64_t);
    VeryLongInt(int32_t x){
      *this = VeryLongInt((uint32_t) x);
    }
  
    VeryLongInt(int64_t x){
      *this = VeryLongInt((uint64_t) x);
    }

    VeryLongInt(unsigned long long x){
      *this = VeryLongInt((uint64_t) x);
    }
  
    VeryLongInt(long long x){
      *this = VeryLongInt((uint64_t) x);
    }
  
    VeryLongInt(char) = delete;
    VeryLongInt(char16_t) = delete;
    VeryLongInt(char32_t) = delete;
    VeryLongInt(wchar_t) = delete;
    VeryLongInt(bool) = delete;
    explicit VeryLongInt(const std::string &);
    explicit VeryLongInt(const char *);
  
    explicit operator bool() const;
  
    size_t numberOfBinaryDigits()const;
    bool isValid()const;
  
    VeryLongInt &operator=(const VeryLongInt &);
    VeryLongInt &operator+=(const VeryLongInt &);
    VeryLongInt &operator-=(const VeryLongInt &);
    VeryLongInt &operator*=(const VeryLongInt &);
    VeryLongInt &operator/=(const VeryLongInt &);
    VeryLongInt &operator%=(const VeryLongInt &);
    VeryLongInt &operator<<=(uint64_t);
    VeryLongInt &operator<<=(uint32_t x){
      *this <<= (uint64_t) x;
      return *this;
    }
  
    VeryLongInt &operator<<=(int32_t x){
      *this <<= (uint64_t) x;
      return *this;
    }
  
    VeryLongInt &operator<<=(int64_t x){
      *this <<= (uint64_t) x;
      return *this;
    }
  
    VeryLongInt &operator<<=(unsigned long long x){
      *this <<= (uint64_t) x;
      return *this;
    }
  
    VeryLongInt &operator<<=(long long x){
      *this <<= (uint64_t) x;
      return *this;
    }
  
    VeryLongInt &operator>>=(uint64_t);
    VeryLongInt &operator>>=(uint32_t x){
      *this >>= (uint64_t) x;
      return *this;
    }
  
    VeryLongInt &operator>>=(int32_t x){
      *this >>= (uint64_t) x;
      return *this;
    }
  
    VeryLongInt &operator>>=(int64_t x){
      *this >>= (uint64_t) x;
      return *this;
    }
  
    VeryLongInt &operator>>=(unsigned long long x){
      *this >>= (uint64_t) x;
      return *this;
    }
  
    VeryLongInt &operator>>=(long long x){
      *this >>= (uint64_t) x;
      return *this;
    }
  
    friend std::ostream & operator<<(std::ostream &, const VeryLongInt &);
  
};

VeryLongInt &operator+(const VeryLongInt &, const VeryLongInt &);
VeryLongInt &operator-(const VeryLongInt &, const VeryLongInt &);
VeryLongInt &operator*(const VeryLongInt &, const VeryLongInt &);
VeryLongInt &operator/(const VeryLongInt &, const VeryLongInt &);
VeryLongInt &operator%(const VeryLongInt &, const VeryLongInt &);
VeryLongInt &operator<<(const VeryLongInt &, unsigned int);
VeryLongInt &operator>>(const VeryLongInt &, unsigned int);

bool operator==(const VeryLongInt &, const VeryLongInt &);
bool operator!=(const VeryLongInt &, const VeryLongInt &);
bool operator<(const VeryLongInt &, const VeryLongInt &);
bool operator<=(const VeryLongInt &, const VeryLongInt &);
bool operator>(const VeryLongInt &, const VeryLongInt &);
bool operator>=(const VeryLongInt &, const VeryLongInt &);

VeryLongInt const &Zero();
VeryLongInt const &NaN();

#endif

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Chat Now And Get Quote