Big Int class

Hi guys,

So, I've been doing some of the problems on Project Euler for a while and it seems a few of them require the manipulation of very large numbers so I decided to start building a large integer class. For now I will just stick to additive operations using positive numbers (addition/multiplication) and later extend it to subtraction and division.
The number is stored dynamically in an unsigned short array on the heap and so far I have written just the constructors/destructor, assignment and extraction overloads. It mostly seems to be working at the moment but I'm still learning about most of this stuff, so I would be really grateful if anyone could point out any poor code practises or suggestions to improve the memory efficiency etc.

One thing I have never used before is exception handling, I have tried to implement some here by having a function, checkformat(). If any element in the array is outside the range 0<x<9, an exception is thrown which is caught and passed as an argument to another function, err_handle() which lets the user know what the error was. Is this an okay use of the try{} catch{} blocks?

BigInt.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#ifndef BIGINTS_H
#define BIGINTS_H

using std::ostream;

class BigInt
{
private:
	unsigned short* number_;	//ptr to an array on the heap
	unsigned length_;			// size of array

	void checkformat( const BigInt& BI );				//placed in try block
	void err_handle(const unsigned short& err_id );		//placed in catch block

public:
	
	BigInt();
	BigInt( const BigInt& BI );
	BigInt( const int& n );
	BigInt( const long& n );
	BigInt( const long long& n );
	~BigInt();
	
	BigInt& operator = (const BigInt& BI);
	BigInt& operator = (const int& n);
	BigInt& operator = (const long& n);
	BigInt& operator = (const long long& n);
	// BigInt& operator + (const BigInt& BI); //To Do

	unsigned short* getnumaddress() const;		//for debuging
	ostream& tostream(ostream& os);				// ostream helper function

	unsigned length() const;					//return number of elements				
	unsigned short at( const unsigned& position ) const;	//element access at 'position'

};

ostream& operator << ( ostream& os, BigInt& BI );

#endif 



BigInts.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include "BigInts.h"
#include <string>


//Constructors / Destructor
BigInt::BigInt():
length_(0),
number_(NULL)
{
}

BigInt::BigInt(const BigInt& BI)
{
	length_ = BI.length();
	number_ = new unsigned short[ length_ ];
	*this = BI;

	try { checkformat(*this); }
	catch(unsigned short err) { err_handle(err); }
}

BigInt::BigInt(const int& n)
{
	long long ncpy = n;
	std::string num = std::to_string(ncpy);
	length_ = num.length();
	number_ = new unsigned short [length_];

	for(unsigned i=0; i<length_; i++) number_[i] = (num[i] - '0');

	try { checkformat(*this); }
	catch(unsigned short err) { err_handle(err); }
}

BigInt::BigInt(const long& n)
{
	long long ncpy = n;
	std::string num = std::to_string(ncpy);
	length_ = num.length();
	number_ = new unsigned short [length_];

	for(unsigned i=0; i<length_; i++) number_[i] = (num[i] - '0');

	try { checkformat(*this); }
	catch(unsigned short err) { err_handle(err); }
}

BigInt::BigInt(const long long& n)
{
	long long ncpy = n;
	std::string num = std::to_string(ncpy);
	length_ = num.length();
	number_ = new unsigned short [length_];

	for(unsigned i=0; i<length_; i++) number_[i] = (num[i] - '0');

	try { checkformat(*this); }
	catch(unsigned short err) { err_handle(err); }
}

BigInt::~BigInt()
{
	if( number_ ) delete [] number_;
}

//Exception Handling
void BigInt::checkformat( const BigInt& BI )
{
	for(unsigned i=0; i<length_; i++)
	{
		if( number_[i]<0 || number_[i]>9 ) throw unsigned short(1);
	}
}

void BigInt::err_handle( const unsigned short& err_id )
{
	switch( err_id )
	{
	case 1:
		std::cerr << "Improperly formatted data, error " << err_id << std::endl;
		break;
	default:
		break;
	}
}

//Operator Overloads

BigInt& BigInt::operator = ( const BigInt& BI )
{
	if( this!=&BI )
	{
		delete [] number_;
		length_ = BI.length();
		new unsigned short [length_];

		for(unsigned i=0; i<length_; i++) number_[i] = BI.at(i);
	}
	return *this;
}

BigInt& BigInt::operator = (const int& n)
{
	BigInt temp(n);
	*this = temp;
	return *this;
}

BigInt& BigInt::operator = (const long& n)
{
	BigInt temp(n);
	*this = temp;
	return *this;
}

BigInt& BigInt::operator = (const long long& n)
{
	BigInt temp(n);
	*this = temp;
	return *this;
}

ostream& BigInt::tostream(ostream& os)
{
	for( unsigned i=0; i<length_; i++) os << number_[i];
	return os;
}

ostream& operator << ( ostream& os, BigInt& BI)
{
	return BI.tostream(os);
}


//other member functions
unsigned BigInt::length() const
{
	return length_;
}

unsigned short BigInt::at( const unsigned& position) const
{
	return position>length_ ? NULL : number_[position];
}

unsigned short* BigInt::getnumaddress() const
{
	return number_;
}
What will be the maximum size of digit your class can handle ? A long long type ?
Sorry, i may not have been clear in the explanation. the large integer is stored as a 1D array such that, say, a 100 digit number is represented by the variable number_[100], where each element represents a digit from 0 to 9, each digit is an unsigned short type and the total number of digits is an unsigned int.
How can a user insert a 100 digit number to your class. I may be missing the details but I can't see this happening ?
Topic archived. No new replies allowed.