Skip to main content
deleted 181 characters in body; edited title
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238

Large Integer Class - Stores Integer Datainteger class for storing integer data as Char Arraya char array

Edit 9 March 2016: As it has been pointed out, this does not use proper C++ components such as std::vector, std::copy and others. My goals in this project were to avoid the use of the standard (or other) library aside from IO.

I am working on a LargeInteger class to store Integers beyond the size of long long as a dynamic character array. I have overloaded most of the relevant operators to be used with the large integers. I would appreciate comments on my implementation.

  • Storing the data as a dynamic char array.
  • The attributes of the operators (friend, overloaded, return type, parameters).

Everything else is fair game, and I welcome any and all criticisms. This is one of the firstdoes not use proper C++ classes I have madecomponents such as std::vector, so I expect that my coding is sub-parstd::copy and others. Without further ado, here isMy goals in this project were to avoid the codeuse of the standard (header firstor other): library aside from I/O.

Everything else is fair game, and I welcome any and all criticisms. This is one of the first C++ classes I have made, so I expect that my coding is sub-par.

LargeInt.h

// LargeInt.h
#ifndef LARGEINT_H
#define LARGEINT_H

#include <iostream>

typedef unsigned int Counter;
typedef char Digit;
typedef unsigned int Index;
typedef bool Sign;

const bool kSignPositive = 0;
const bool kSignNegative = 1;
const bool kCarryTrue = 1;
const bool kCarryFalse = 0;
const bool kBorrowTrue = 1;
const bool kBorrowFalse = 0;

const Counter kDefaultCounterValue = 0;

const Digit kDefaultDigitValue = 0;
const Digit kMinDigitValue = 0;
const Digit kMaxDigitValue = 9;
const Digit kRadix = 10;

const Index kFirstIndex = 0;

const size_t kByteSize = 8;
const size_t kMinLength = 1;

namespace helper_templates
{
    // Count Digits
    template <typename T>
    Counter TCountDigits(T x);

    // Get Sign
    template <typename T>
    bool TGetSign(T x);
}

class LargeInt
{
    private:
        Sign sign_;
        size_t length_;
        Digit* data_;
        
    public:
        /*
         * Constructors
         */
        
        // Default
        LargeInt();
        
        // Copy
        LargeInt(const LargeInt& x);
        
        // Copy and Resize
        LargeInt(const Sign sign, const size_t length, const Digit* data);
        
        // Integer Type
        LargeInt(const long long x);
        
        /*
         * Destructor
         */
        
        ~LargeInt();
        
        /*
         * Operators
         */

        // Assignemnt
        LargeInt& operator=(const LargeInt& x);
        
        // Negation
        LargeInt operator-();
        
        // Addition
        friend LargeInt operator+(LargeInt x, const LargeInt& y);
        
        // Addition Assignment
        LargeInt& operator+=(const LargeInt& x);
        
        // Subtraction
        friend LargeInt operator-(LargeInt x, const LargeInt& y);
        
        // Subtraction Assignment
        LargeInt& operator-=(const LargeInt& x);
        
        // Preincrement
        LargeInt& operator++();
        
        // Postincrement
        LargeInt operator++(int);
        
        // Predecrement
        LargeInt& operator--();
        
        // Postdecrement
        LargeInt operator--(int);
        
        // Not
        bool operator!();
        
        // Equality
        friend bool operator==(const LargeInt& x, const LargeInt& y);
        
        // Inequality
        friend bool operator!=(const LargeInt& x, const LargeInt& y);
        
        // Greater Than
        friend bool operator>(const LargeInt& x, const LargeInt& y);
        
        // Greater Than or Equal To
        friend bool operator>=(const LargeInt& x, const LargeInt& y);
        
        // Less Than
        friend bool operator<(const LargeInt& x, const LargeInt& y);
        
        // Less Than or Equal To
        friend bool operator <=(const LargeInt& x, const LargeInt& y);
        
        // Insertion
        friend std::ostream& operator<<(std::ostream& out,
            const LargeInt& x);
        
        /*
         * Functions
         */
         
        // Absolute Value
        LargeInt Abs() const;
};

#endif

And now the implementation:LargeInt.C

// LargeInt.C
#include "LargeInt.h"

// Count Digits
template <typename T>
Counter helper_templates::TCountDigits(T x)
{
    Counter c = kDefaultCounterValue;
    while(x)
    {
        x /= kRadix;
        c++;
    }
    return c;
}

// Get Sign
template <typename T>
Sign helper_templates::TGetSign(T x)
{
    long long mask = 0;
    mask |= 1 << ((sizeof(x) * kByteSize) - 1);
    return (mask & x) >> ((sizeof(x) * kByteSize) - 1);
}

/*
 * Constructors
 */

 // Default
LargeInt::LargeInt()
    : sign_(kSignPositive), length_(kMinLength), data_(new Digit[kMinLength])
{
     data_[kFirstIndex] = kDefaultDigitValue;
}

// Copy
LargeInt::LargeInt(const LargeInt& x)
    : sign_(x.sign_), length_(x.length_), data_(new Digit[x.length_])
{
    for(Index i = kFirstIndex; i < length_; i++)
    {
        data_[i] = x.data_[i];
    }
}

// Copy and Resize
LargeInt::LargeInt(const Sign sign, const size_t length, const Digit* data)
    : sign_(sign), length_(length), data_(new Digit[length_])
{
    for(Index i = kFirstIndex; i < length_; i++)
    {
        data_[i] = data[i];
    }
}

// Integer Type
LargeInt::LargeInt(long long x)
    : sign_(helper_templates::TGetSign(x)),
        length_(helper_templates::TCountDigits(x)),
        data_(new Digit[length_])
{
    if(sign_ == kSignNegative)
    {
        x = -x;
    }
    for(Index i = kFirstIndex; i < length_; i++)
    {
        Digit d = x % kRadix;
        data_[i] = d;
        x /= kRadix;
    }
}

/*
 * Destructor
 */

LargeInt::~LargeInt()
{
    delete [] data_;
}

/*
 * Operators
 */
 
// Assignment
LargeInt& LargeInt::operator=(const LargeInt& x)
{
    if(this != &x)
    {
        this->sign_ = x.sign_;
        this->length_ = x.length_;
        for(Index i = kFirstIndex; i < this->length_; i++)
        {
            this->data_[i] = x.data_[i];
        }
    }
    return *this;
}

// Negation
LargeInt LargeInt::operator-()
{
    return LargeInt(!this->sign_, this->length_, this->data_);
}

// Addition
LargeInt operator+(LargeInt x, const LargeInt& y)
{
    return x += y;
}

// Addition Assignment
LargeInt& LargeInt::operator+=(const LargeInt& x)
{
    LargeInt sum;
    Digit d;
    Digit carry = kCarryFalse;
    Index i;
    if(this->sign_ == kSignPositive && x.sign_ == kSignPositive)
    {
        if(*this >= x)
        {
            sum.length_ = this->length_ + kMinLength;
            for(i = kFirstIndex; i < x.length_; i++)
            {
                d = this->data_[i] + x.data_[i] + carry;
                if(d > kMaxDigitValue)
                {
                    d %= kRadix;
                    carry = kCarryTrue;
                }
                else
                {
                    carry = kCarryFalse;
                }
                sum.data_[i] = d;
            }
            while(i < this->length_)
            {
                d = this->data_[i] + carry;
                if(d > kMaxDigitValue)
                {
                    d %= kRadix;
                    carry = kCarryTrue;
                }
                else
                {
                    carry = kCarryFalse;
                }
                sum.data_[i] = d;
                i++;
            }
            if(!carry)
            {
                *this = LargeInt(sum.sign_, sum.length_ - kMinLength,
                    sum.data_);
            }
            else
            {
                *this = sum;
            }
        }
        else
        {
            *this = x + *this;
        }
    }
    else if(this->sign_ == kSignPositive)
    {
        *this = *this - x;
    }
    else if(x.sign_ == kSignPositive)
    {
        *this = x - *this;
    }
    else
    {
        *this = -(x.Abs() + this->Abs());
    }
    return *this;
}

// Subtraction
LargeInt operator-(LargeInt x, const LargeInt& y)
{
    return x -= y;
}

// Subtraction Assignment
LargeInt& LargeInt::operator-=(const LargeInt& x)
{
    LargeInt difference;
    Digit d;
    Digit borrow = kBorrowFalse;
    Index i;
    if(x.sign_ == kSignNegative)
    {
        *this = *this + x.Abs();
    }
    else if(this->sign_ == kSignNegative)
    {
        *this = -(this->Abs() + x);
    }
    else
    {
        if(*this > x)
        {
            difference.length_ = this->length_;
            for(i = kFirstIndex; i < x.length_; i++)
            {
                d = this->data_[i] - x.data_[i] - borrow;
                if(d < kDefaultDigitValue)
                {
                    d += kRadix;
                    borrow = kBorrowTrue;
                }
                else
                {
                    borrow = kBorrowFalse;
                }
                difference.data_[i] = d;
            }
            while(i < this->length_)
            {
                d = this->data_[i] - borrow;
                if(d < kDefaultDigitValue)
                {
                    d += kRadix;
                    borrow = kBorrowTrue;
                }
                else
                {
                    borrow = kBorrowFalse;
                }
                difference.data_[i] = d;
                i++;
            }
            for(i = difference.length_; i > kFirstIndex; i--)
            {
                if(difference.data_[i - 1] == kDefaultDigitValue)
                {
                    difference.length_--;
                }
                else
                {
                    break;
                }
            }
            *this = LargeInt(kSignPositive, difference.length_,
                difference.data_);
        }
        else if(x > *this)
        {
            *this = -(x - *this);
        }
        else
        {
            *this = LargeInt();
        }
    }
    return *this;
}

// Preincrement
LargeInt& LargeInt::operator++()
{
    *this += 1;
    return *this;
}

// Postincrement
LargeInt LargeInt::operator++(int)
{
    LargeInt temp(*this);
    ++*this;
    return temp;
}

// Predecrement
LargeInt& LargeInt::operator--()
{
    *this -= 1;
    return *this;
}

// Postdecrement
LargeInt LargeInt::operator--(int)
{
    LargeInt temp(*this);
    --*this;
    return temp;
}

// Not
bool LargeInt::operator!()
{
    bool isNot;
    if(*this == LargeInt())
    {
        isNot = true;
    }
    else
    {
        isNot = false;
    }
    return isNot;
}

// Equality
bool operator==(const LargeInt& x, const LargeInt& y)
{
    bool isEqual;
    if(x.sign_ != y.sign_)
    {
        isEqual = false;
    }
    else if(x.length_ != y.length_)
    {
        isEqual = false;
    }
    else
    {
        for(Index i = kFirstIndex; i < x.length_; i++)
        {
            if(x.data_[i] != y.data_[i])
            {
                isEqual = false;
                break;
            }
            isEqual = true;
        }
    }
    return isEqual;
}

// Inequality
bool operator!=(const LargeInt& x, const LargeInt& y)
{
    return !(x == y);
}

// Greater Than
bool operator>(const LargeInt& x, const LargeInt& y)
{
    bool isGreater;
    if(x.sign_ == kSignPositive && y.sign_ == kSignPositive)
    {
        if(x.length_ == y.length_)
        {
            for(Index i = x.length_; i > kFirstIndex; i--)
            {
                if(x.data_[i - i] > y.data_[i - 1])
                {
                    isGreater = true;
                    break;
                }
                else
                {
                    isGreater = false;
                }
            }
        }
        else if(x.length_ > y.length_)
        {
            isGreater = true;
        }
        else
        {
            isGreater = false;
        }
    }
    else if(x.sign_ == kSignPositive)
    {
        isGreater = true;
    }
    else if(y.sign_ == kSignPositive)
    {
        isGreater = false;
    }
    else
    {
        isGreater = y.Abs() > x.Abs();
    }
    return isGreater;
}

// Greater Than or Equal To
bool operator>=(const LargeInt& x, const LargeInt& y)
{
    return (x > y) || (x == y);
}

// Less Than
bool operator<(const LargeInt& x, const LargeInt& y)
{
    return y > x;
}

// Less Than or Equal To
bool operator <=(const LargeInt& x, const LargeInt& y)
{
    return (x < y) || (x == y);
}

// Insertion
std::ostream& operator<<(std::ostream& out, const LargeInt& x)
{
    if(x.sign_ == kSignNegative)
    {
        out << '-';
    }
    for(Index i = x.length_; i > kFirstIndex; i--)
    {
        out << +x.data_[i - 1];
    }
    return out;
}

/*
 * Functions
 */

// Absolute Value
LargeInt LargeInt::Abs() const
{
    return LargeInt(kSignPositive, this->length_, this->data_);
}

Large Integer Class - Stores Integer Data as Char Array

Edit 9 March 2016: As it has been pointed out, this does not use proper C++ components such as std::vector, std::copy and others. My goals in this project were to avoid the use of the standard (or other) library aside from IO.

I am working on a LargeInteger class to store Integers beyond the size of long long as a dynamic character array. I have overloaded most of the relevant operators to be used with the large integers. I would appreciate comments on my implementation.

  • Storing the data as a dynamic char array.
  • The attributes of the operators (friend, overloaded, return type, parameters).

Everything else is fair game, and I welcome any and all criticisms. This is one of the first C++ classes I have made, so I expect that my coding is sub-par. Without further ado, here is the code (header first):

// LargeInt.h
#ifndef LARGEINT_H
#define LARGEINT_H

#include <iostream>

typedef unsigned int Counter;
typedef char Digit;
typedef unsigned int Index;
typedef bool Sign;

const bool kSignPositive = 0;
const bool kSignNegative = 1;
const bool kCarryTrue = 1;
const bool kCarryFalse = 0;
const bool kBorrowTrue = 1;
const bool kBorrowFalse = 0;

const Counter kDefaultCounterValue = 0;

const Digit kDefaultDigitValue = 0;
const Digit kMinDigitValue = 0;
const Digit kMaxDigitValue = 9;
const Digit kRadix = 10;

const Index kFirstIndex = 0;

const size_t kByteSize = 8;
const size_t kMinLength = 1;

namespace helper_templates
{
    // Count Digits
    template <typename T>
    Counter TCountDigits(T x);

    // Get Sign
    template <typename T>
    bool TGetSign(T x);
}

class LargeInt
{
    private:
        Sign sign_;
        size_t length_;
        Digit* data_;
        
    public:
        /*
         * Constructors
         */
        
        // Default
        LargeInt();
        
        // Copy
        LargeInt(const LargeInt& x);
        
        // Copy and Resize
        LargeInt(const Sign sign, const size_t length, const Digit* data);
        
        // Integer Type
        LargeInt(const long long x);
        
        /*
         * Destructor
         */
        
        ~LargeInt();
        
        /*
         * Operators
         */

        // Assignemnt
        LargeInt& operator=(const LargeInt& x);
        
        // Negation
        LargeInt operator-();
        
        // Addition
        friend LargeInt operator+(LargeInt x, const LargeInt& y);
        
        // Addition Assignment
        LargeInt& operator+=(const LargeInt& x);
        
        // Subtraction
        friend LargeInt operator-(LargeInt x, const LargeInt& y);
        
        // Subtraction Assignment
        LargeInt& operator-=(const LargeInt& x);
        
        // Preincrement
        LargeInt& operator++();
        
        // Postincrement
        LargeInt operator++(int);
        
        // Predecrement
        LargeInt& operator--();
        
        // Postdecrement
        LargeInt operator--(int);
        
        // Not
        bool operator!();
        
        // Equality
        friend bool operator==(const LargeInt& x, const LargeInt& y);
        
        // Inequality
        friend bool operator!=(const LargeInt& x, const LargeInt& y);
        
        // Greater Than
        friend bool operator>(const LargeInt& x, const LargeInt& y);
        
        // Greater Than or Equal To
        friend bool operator>=(const LargeInt& x, const LargeInt& y);
        
        // Less Than
        friend bool operator<(const LargeInt& x, const LargeInt& y);
        
        // Less Than or Equal To
        friend bool operator <=(const LargeInt& x, const LargeInt& y);
        
        // Insertion
        friend std::ostream& operator<<(std::ostream& out,
            const LargeInt& x);
        
        /*
         * Functions
         */
         
        // Absolute Value
        LargeInt Abs() const;
};

#endif

And now the implementation:

// LargeInt.C
#include "LargeInt.h"

// Count Digits
template <typename T>
Counter helper_templates::TCountDigits(T x)
{
    Counter c = kDefaultCounterValue;
    while(x)
    {
        x /= kRadix;
        c++;
    }
    return c;
}

// Get Sign
template <typename T>
Sign helper_templates::TGetSign(T x)
{
    long long mask = 0;
    mask |= 1 << ((sizeof(x) * kByteSize) - 1);
    return (mask & x) >> ((sizeof(x) * kByteSize) - 1);
}

/*
 * Constructors
 */

 // Default
LargeInt::LargeInt()
    : sign_(kSignPositive), length_(kMinLength), data_(new Digit[kMinLength])
{
     data_[kFirstIndex] = kDefaultDigitValue;
}

// Copy
LargeInt::LargeInt(const LargeInt& x)
    : sign_(x.sign_), length_(x.length_), data_(new Digit[x.length_])
{
    for(Index i = kFirstIndex; i < length_; i++)
    {
        data_[i] = x.data_[i];
    }
}

// Copy and Resize
LargeInt::LargeInt(const Sign sign, const size_t length, const Digit* data)
    : sign_(sign), length_(length), data_(new Digit[length_])
{
    for(Index i = kFirstIndex; i < length_; i++)
    {
        data_[i] = data[i];
    }
}

// Integer Type
LargeInt::LargeInt(long long x)
    : sign_(helper_templates::TGetSign(x)),
        length_(helper_templates::TCountDigits(x)),
        data_(new Digit[length_])
{
    if(sign_ == kSignNegative)
    {
        x = -x;
    }
    for(Index i = kFirstIndex; i < length_; i++)
    {
        Digit d = x % kRadix;
        data_[i] = d;
        x /= kRadix;
    }
}

/*
 * Destructor
 */

LargeInt::~LargeInt()
{
    delete [] data_;
}

/*
 * Operators
 */
 
// Assignment
LargeInt& LargeInt::operator=(const LargeInt& x)
{
    if(this != &x)
    {
        this->sign_ = x.sign_;
        this->length_ = x.length_;
        for(Index i = kFirstIndex; i < this->length_; i++)
        {
            this->data_[i] = x.data_[i];
        }
    }
    return *this;
}

// Negation
LargeInt LargeInt::operator-()
{
    return LargeInt(!this->sign_, this->length_, this->data_);
}

// Addition
LargeInt operator+(LargeInt x, const LargeInt& y)
{
    return x += y;
}

// Addition Assignment
LargeInt& LargeInt::operator+=(const LargeInt& x)
{
    LargeInt sum;
    Digit d;
    Digit carry = kCarryFalse;
    Index i;
    if(this->sign_ == kSignPositive && x.sign_ == kSignPositive)
    {
        if(*this >= x)
        {
            sum.length_ = this->length_ + kMinLength;
            for(i = kFirstIndex; i < x.length_; i++)
            {
                d = this->data_[i] + x.data_[i] + carry;
                if(d > kMaxDigitValue)
                {
                    d %= kRadix;
                    carry = kCarryTrue;
                }
                else
                {
                    carry = kCarryFalse;
                }
                sum.data_[i] = d;
            }
            while(i < this->length_)
            {
                d = this->data_[i] + carry;
                if(d > kMaxDigitValue)
                {
                    d %= kRadix;
                    carry = kCarryTrue;
                }
                else
                {
                    carry = kCarryFalse;
                }
                sum.data_[i] = d;
                i++;
            }
            if(!carry)
            {
                *this = LargeInt(sum.sign_, sum.length_ - kMinLength,
                    sum.data_);
            }
            else
            {
                *this = sum;
            }
        }
        else
        {
            *this = x + *this;
        }
    }
    else if(this->sign_ == kSignPositive)
    {
        *this = *this - x;
    }
    else if(x.sign_ == kSignPositive)
    {
        *this = x - *this;
    }
    else
    {
        *this = -(x.Abs() + this->Abs());
    }
    return *this;
}

// Subtraction
LargeInt operator-(LargeInt x, const LargeInt& y)
{
    return x -= y;
}

// Subtraction Assignment
LargeInt& LargeInt::operator-=(const LargeInt& x)
{
    LargeInt difference;
    Digit d;
    Digit borrow = kBorrowFalse;
    Index i;
    if(x.sign_ == kSignNegative)
    {
        *this = *this + x.Abs();
    }
    else if(this->sign_ == kSignNegative)
    {
        *this = -(this->Abs() + x);
    }
    else
    {
        if(*this > x)
        {
            difference.length_ = this->length_;
            for(i = kFirstIndex; i < x.length_; i++)
            {
                d = this->data_[i] - x.data_[i] - borrow;
                if(d < kDefaultDigitValue)
                {
                    d += kRadix;
                    borrow = kBorrowTrue;
                }
                else
                {
                    borrow = kBorrowFalse;
                }
                difference.data_[i] = d;
            }
            while(i < this->length_)
            {
                d = this->data_[i] - borrow;
                if(d < kDefaultDigitValue)
                {
                    d += kRadix;
                    borrow = kBorrowTrue;
                }
                else
                {
                    borrow = kBorrowFalse;
                }
                difference.data_[i] = d;
                i++;
            }
            for(i = difference.length_; i > kFirstIndex; i--)
            {
                if(difference.data_[i - 1] == kDefaultDigitValue)
                {
                    difference.length_--;
                }
                else
                {
                    break;
                }
            }
            *this = LargeInt(kSignPositive, difference.length_,
                difference.data_);
        }
        else if(x > *this)
        {
            *this = -(x - *this);
        }
        else
        {
            *this = LargeInt();
        }
    }
    return *this;
}

// Preincrement
LargeInt& LargeInt::operator++()
{
    *this += 1;
    return *this;
}

// Postincrement
LargeInt LargeInt::operator++(int)
{
    LargeInt temp(*this);
    ++*this;
    return temp;
}

// Predecrement
LargeInt& LargeInt::operator--()
{
    *this -= 1;
    return *this;
}

// Postdecrement
LargeInt LargeInt::operator--(int)
{
    LargeInt temp(*this);
    --*this;
    return temp;
}

// Not
bool LargeInt::operator!()
{
    bool isNot;
    if(*this == LargeInt())
    {
        isNot = true;
    }
    else
    {
        isNot = false;
    }
    return isNot;
}

// Equality
bool operator==(const LargeInt& x, const LargeInt& y)
{
    bool isEqual;
    if(x.sign_ != y.sign_)
    {
        isEqual = false;
    }
    else if(x.length_ != y.length_)
    {
        isEqual = false;
    }
    else
    {
        for(Index i = kFirstIndex; i < x.length_; i++)
        {
            if(x.data_[i] != y.data_[i])
            {
                isEqual = false;
                break;
            }
            isEqual = true;
        }
    }
    return isEqual;
}

// Inequality
bool operator!=(const LargeInt& x, const LargeInt& y)
{
    return !(x == y);
}

// Greater Than
bool operator>(const LargeInt& x, const LargeInt& y)
{
    bool isGreater;
    if(x.sign_ == kSignPositive && y.sign_ == kSignPositive)
    {
        if(x.length_ == y.length_)
        {
            for(Index i = x.length_; i > kFirstIndex; i--)
            {
                if(x.data_[i - i] > y.data_[i - 1])
                {
                    isGreater = true;
                    break;
                }
                else
                {
                    isGreater = false;
                }
            }
        }
        else if(x.length_ > y.length_)
        {
            isGreater = true;
        }
        else
        {
            isGreater = false;
        }
    }
    else if(x.sign_ == kSignPositive)
    {
        isGreater = true;
    }
    else if(y.sign_ == kSignPositive)
    {
        isGreater = false;
    }
    else
    {
        isGreater = y.Abs() > x.Abs();
    }
    return isGreater;
}

// Greater Than or Equal To
bool operator>=(const LargeInt& x, const LargeInt& y)
{
    return (x > y) || (x == y);
}

// Less Than
bool operator<(const LargeInt& x, const LargeInt& y)
{
    return y > x;
}

// Less Than or Equal To
bool operator <=(const LargeInt& x, const LargeInt& y)
{
    return (x < y) || (x == y);
}

// Insertion
std::ostream& operator<<(std::ostream& out, const LargeInt& x)
{
    if(x.sign_ == kSignNegative)
    {
        out << '-';
    }
    for(Index i = x.length_; i > kFirstIndex; i--)
    {
        out << +x.data_[i - 1];
    }
    return out;
}

/*
 * Functions
 */

// Absolute Value
LargeInt LargeInt::Abs() const
{
    return LargeInt(kSignPositive, this->length_, this->data_);
}

Large integer class for storing integer data as a char array

I am working on a LargeInteger class to store Integers beyond the size of long long as a dynamic character array. I have overloaded most of the relevant operators to be used with the large integers.

  • Storing the data as a dynamic char array
  • The attributes of the operators (friend, overloaded, return type, parameters)

This does not use proper C++ components such as std::vector, std::copy and others. My goals in this project were to avoid the use of the standard (or other) library aside from I/O.

Everything else is fair game, and I welcome any and all criticisms. This is one of the first C++ classes I have made, so I expect that my coding is sub-par.

LargeInt.h

#ifndef LARGEINT_H
#define LARGEINT_H

#include <iostream>

typedef unsigned int Counter;
typedef char Digit;
typedef unsigned int Index;
typedef bool Sign;

const bool kSignPositive = 0;
const bool kSignNegative = 1;
const bool kCarryTrue = 1;
const bool kCarryFalse = 0;
const bool kBorrowTrue = 1;
const bool kBorrowFalse = 0;

const Counter kDefaultCounterValue = 0;

const Digit kDefaultDigitValue = 0;
const Digit kMinDigitValue = 0;
const Digit kMaxDigitValue = 9;
const Digit kRadix = 10;

const Index kFirstIndex = 0;

const size_t kByteSize = 8;
const size_t kMinLength = 1;

namespace helper_templates
{
    // Count Digits
    template <typename T>
    Counter TCountDigits(T x);

    // Get Sign
    template <typename T>
    bool TGetSign(T x);
}

class LargeInt
{
    private:
        Sign sign_;
        size_t length_;
        Digit* data_;
        
    public:
        /*
         * Constructors
         */
        
        // Default
        LargeInt();
        
        // Copy
        LargeInt(const LargeInt& x);
        
        // Copy and Resize
        LargeInt(const Sign sign, const size_t length, const Digit* data);
        
        // Integer Type
        LargeInt(const long long x);
        
        /*
         * Destructor
         */
        
        ~LargeInt();
        
        /*
         * Operators
         */

        // Assignemnt
        LargeInt& operator=(const LargeInt& x);
        
        // Negation
        LargeInt operator-();
        
        // Addition
        friend LargeInt operator+(LargeInt x, const LargeInt& y);
        
        // Addition Assignment
        LargeInt& operator+=(const LargeInt& x);
        
        // Subtraction
        friend LargeInt operator-(LargeInt x, const LargeInt& y);
        
        // Subtraction Assignment
        LargeInt& operator-=(const LargeInt& x);
        
        // Preincrement
        LargeInt& operator++();
        
        // Postincrement
        LargeInt operator++(int);
        
        // Predecrement
        LargeInt& operator--();
        
        // Postdecrement
        LargeInt operator--(int);
        
        // Not
        bool operator!();
        
        // Equality
        friend bool operator==(const LargeInt& x, const LargeInt& y);
        
        // Inequality
        friend bool operator!=(const LargeInt& x, const LargeInt& y);
        
        // Greater Than
        friend bool operator>(const LargeInt& x, const LargeInt& y);
        
        // Greater Than or Equal To
        friend bool operator>=(const LargeInt& x, const LargeInt& y);
        
        // Less Than
        friend bool operator<(const LargeInt& x, const LargeInt& y);
        
        // Less Than or Equal To
        friend bool operator <=(const LargeInt& x, const LargeInt& y);
        
        // Insertion
        friend std::ostream& operator<<(std::ostream& out,
            const LargeInt& x);
        
        /*
         * Functions
         */
         
        // Absolute Value
        LargeInt Abs() const;
};

#endif

LargeInt.C

#include "LargeInt.h"

// Count Digits
template <typename T>
Counter helper_templates::TCountDigits(T x)
{
    Counter c = kDefaultCounterValue;
    while(x)
    {
        x /= kRadix;
        c++;
    }
    return c;
}

// Get Sign
template <typename T>
Sign helper_templates::TGetSign(T x)
{
    long long mask = 0;
    mask |= 1 << ((sizeof(x) * kByteSize) - 1);
    return (mask & x) >> ((sizeof(x) * kByteSize) - 1);
}

/*
 * Constructors
 */

 // Default
LargeInt::LargeInt()
    : sign_(kSignPositive), length_(kMinLength), data_(new Digit[kMinLength])
{
     data_[kFirstIndex] = kDefaultDigitValue;
}

// Copy
LargeInt::LargeInt(const LargeInt& x)
    : sign_(x.sign_), length_(x.length_), data_(new Digit[x.length_])
{
    for(Index i = kFirstIndex; i < length_; i++)
    {
        data_[i] = x.data_[i];
    }
}

// Copy and Resize
LargeInt::LargeInt(const Sign sign, const size_t length, const Digit* data)
    : sign_(sign), length_(length), data_(new Digit[length_])
{
    for(Index i = kFirstIndex; i < length_; i++)
    {
        data_[i] = data[i];
    }
}

// Integer Type
LargeInt::LargeInt(long long x)
    : sign_(helper_templates::TGetSign(x)),
        length_(helper_templates::TCountDigits(x)),
        data_(new Digit[length_])
{
    if(sign_ == kSignNegative)
    {
        x = -x;
    }
    for(Index i = kFirstIndex; i < length_; i++)
    {
        Digit d = x % kRadix;
        data_[i] = d;
        x /= kRadix;
    }
}

/*
 * Destructor
 */

LargeInt::~LargeInt()
{
    delete [] data_;
}

/*
 * Operators
 */
 
// Assignment
LargeInt& LargeInt::operator=(const LargeInt& x)
{
    if(this != &x)
    {
        this->sign_ = x.sign_;
        this->length_ = x.length_;
        for(Index i = kFirstIndex; i < this->length_; i++)
        {
            this->data_[i] = x.data_[i];
        }
    }
    return *this;
}

// Negation
LargeInt LargeInt::operator-()
{
    return LargeInt(!this->sign_, this->length_, this->data_);
}

// Addition
LargeInt operator+(LargeInt x, const LargeInt& y)
{
    return x += y;
}

// Addition Assignment
LargeInt& LargeInt::operator+=(const LargeInt& x)
{
    LargeInt sum;
    Digit d;
    Digit carry = kCarryFalse;
    Index i;
    if(this->sign_ == kSignPositive && x.sign_ == kSignPositive)
    {
        if(*this >= x)
        {
            sum.length_ = this->length_ + kMinLength;
            for(i = kFirstIndex; i < x.length_; i++)
            {
                d = this->data_[i] + x.data_[i] + carry;
                if(d > kMaxDigitValue)
                {
                    d %= kRadix;
                    carry = kCarryTrue;
                }
                else
                {
                    carry = kCarryFalse;
                }
                sum.data_[i] = d;
            }
            while(i < this->length_)
            {
                d = this->data_[i] + carry;
                if(d > kMaxDigitValue)
                {
                    d %= kRadix;
                    carry = kCarryTrue;
                }
                else
                {
                    carry = kCarryFalse;
                }
                sum.data_[i] = d;
                i++;
            }
            if(!carry)
            {
                *this = LargeInt(sum.sign_, sum.length_ - kMinLength,
                    sum.data_);
            }
            else
            {
                *this = sum;
            }
        }
        else
        {
            *this = x + *this;
        }
    }
    else if(this->sign_ == kSignPositive)
    {
        *this = *this - x;
    }
    else if(x.sign_ == kSignPositive)
    {
        *this = x - *this;
    }
    else
    {
        *this = -(x.Abs() + this->Abs());
    }
    return *this;
}

// Subtraction
LargeInt operator-(LargeInt x, const LargeInt& y)
{
    return x -= y;
}

// Subtraction Assignment
LargeInt& LargeInt::operator-=(const LargeInt& x)
{
    LargeInt difference;
    Digit d;
    Digit borrow = kBorrowFalse;
    Index i;
    if(x.sign_ == kSignNegative)
    {
        *this = *this + x.Abs();
    }
    else if(this->sign_ == kSignNegative)
    {
        *this = -(this->Abs() + x);
    }
    else
    {
        if(*this > x)
        {
            difference.length_ = this->length_;
            for(i = kFirstIndex; i < x.length_; i++)
            {
                d = this->data_[i] - x.data_[i] - borrow;
                if(d < kDefaultDigitValue)
                {
                    d += kRadix;
                    borrow = kBorrowTrue;
                }
                else
                {
                    borrow = kBorrowFalse;
                }
                difference.data_[i] = d;
            }
            while(i < this->length_)
            {
                d = this->data_[i] - borrow;
                if(d < kDefaultDigitValue)
                {
                    d += kRadix;
                    borrow = kBorrowTrue;
                }
                else
                {
                    borrow = kBorrowFalse;
                }
                difference.data_[i] = d;
                i++;
            }
            for(i = difference.length_; i > kFirstIndex; i--)
            {
                if(difference.data_[i - 1] == kDefaultDigitValue)
                {
                    difference.length_--;
                }
                else
                {
                    break;
                }
            }
            *this = LargeInt(kSignPositive, difference.length_,
                difference.data_);
        }
        else if(x > *this)
        {
            *this = -(x - *this);
        }
        else
        {
            *this = LargeInt();
        }
    }
    return *this;
}

// Preincrement
LargeInt& LargeInt::operator++()
{
    *this += 1;
    return *this;
}

// Postincrement
LargeInt LargeInt::operator++(int)
{
    LargeInt temp(*this);
    ++*this;
    return temp;
}

// Predecrement
LargeInt& LargeInt::operator--()
{
    *this -= 1;
    return *this;
}

// Postdecrement
LargeInt LargeInt::operator--(int)
{
    LargeInt temp(*this);
    --*this;
    return temp;
}

// Not
bool LargeInt::operator!()
{
    bool isNot;
    if(*this == LargeInt())
    {
        isNot = true;
    }
    else
    {
        isNot = false;
    }
    return isNot;
}

// Equality
bool operator==(const LargeInt& x, const LargeInt& y)
{
    bool isEqual;
    if(x.sign_ != y.sign_)
    {
        isEqual = false;
    }
    else if(x.length_ != y.length_)
    {
        isEqual = false;
    }
    else
    {
        for(Index i = kFirstIndex; i < x.length_; i++)
        {
            if(x.data_[i] != y.data_[i])
            {
                isEqual = false;
                break;
            }
            isEqual = true;
        }
    }
    return isEqual;
}

// Inequality
bool operator!=(const LargeInt& x, const LargeInt& y)
{
    return !(x == y);
}

// Greater Than
bool operator>(const LargeInt& x, const LargeInt& y)
{
    bool isGreater;
    if(x.sign_ == kSignPositive && y.sign_ == kSignPositive)
    {
        if(x.length_ == y.length_)
        {
            for(Index i = x.length_; i > kFirstIndex; i--)
            {
                if(x.data_[i - i] > y.data_[i - 1])
                {
                    isGreater = true;
                    break;
                }
                else
                {
                    isGreater = false;
                }
            }
        }
        else if(x.length_ > y.length_)
        {
            isGreater = true;
        }
        else
        {
            isGreater = false;
        }
    }
    else if(x.sign_ == kSignPositive)
    {
        isGreater = true;
    }
    else if(y.sign_ == kSignPositive)
    {
        isGreater = false;
    }
    else
    {
        isGreater = y.Abs() > x.Abs();
    }
    return isGreater;
}

// Greater Than or Equal To
bool operator>=(const LargeInt& x, const LargeInt& y)
{
    return (x > y) || (x == y);
}

// Less Than
bool operator<(const LargeInt& x, const LargeInt& y)
{
    return y > x;
}

// Less Than or Equal To
bool operator <=(const LargeInt& x, const LargeInt& y)
{
    return (x < y) || (x == y);
}

// Insertion
std::ostream& operator<<(std::ostream& out, const LargeInt& x)
{
    if(x.sign_ == kSignNegative)
    {
        out << '-';
    }
    for(Index i = x.length_; i > kFirstIndex; i--)
    {
        out << +x.data_[i - 1];
    }
    return out;
}

/*
 * Functions
 */

// Absolute Value
LargeInt LargeInt::Abs() const
{
    return LargeInt(kSignPositive, this->length_, this->data_);
}
added 230 characters in body
Source Link

Edit 9 March 2016: As it has been pointed out, this does not use proper C++ components such as std::vector, std::copy and others. My goals in this project were to avoid the use of the standard (or other) library aside from IO.

Edit 9 March 2016: As it has been pointed out, this does not use proper C++ components such as std::vector, std::copy and others. My goals in this project were to avoid the use of the standard (or other) library aside from IO.

deleted 22 characters in body; edited tags
Source Link
200_success
  • 145.6k
  • 22
  • 191
  • 481

Thanks in advance!

Thanks in advance!

Source Link
Loading