defining operator+

Hello all, I have been getting great advice from the Beginners forum, but it seems this program that I am working on will require more than beginners' help now. I am, hopefully, almost done with this program, but just need a little help with the last part. The program asks the user to input a big natural number, which is inputted as a string. Then the string is converted to an integer and stored in a vector in blocks of 8 starting from the end. For example: s="1234567891011", then vec[0]=67891011 and vec[1]=12345. The user will input another big natural number and the same thing will happen.

This is where my problem starts. I need to add both the inputted numbers and then output them as a string. I need to add the operator+ method somewhere in my Big_Nat class, but I'm not sure how to do so. Here is what I have so far:

big_nat.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef big_nat_h
#define big_nat_h
#include <iostream>
#include <string>
#include <vector>

class Big_Nat {
private:
	int num_strings;
	std::vector<int> vec;

public:
	Big_Nat(std::string);
	std::string to_string();
};
#endif 

big_nat.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
#include "big_nat.h"
#include <iostream>
#include <string>
#include <cstdlib>
#include <sstream>

Big_Nat::Big_Nat(std::string s)
{
	int current_coefficient;
	int sub_strings;
	int rem_sub_strings;
	int len;
	std::string holder;

	sub_strings = s.length()/8;
	rem_sub_strings = s.length()%8;
	len = s.length();

	for(int i=0; i<sub_strings; i++)
	{
		holder = s.substr(len-8*(i+1),8);
		current_coefficient = atoi(holder.c_str());
		vec.push_back(current_coefficient);
	}

	if(rem_sub_strings)
	{
		holder = s.substr(0, rem_sub_strings);
		current_coefficient = atoi(holder.c_str());
		vec.push_back(current_coefficient);
		num_strings=sub_strings+1;
	}
};

std::string Big_Nat::to_string()
{
	std::stringstream ss;
	std::string stringout="\0";
	int vec_string;
	for(int j=0;j<num_strings;j++)
	{
		vec_string = vec.back();
		vec.pop_back();
		ss << vec_string; ;	
	}
	stringout = ss.str();
	return stringout;
};


Big_Nat_test.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "big_nat.h"
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s;
	cout << "Give x : "; getline(cin,s,'\n');
	Big_Nat x(s);
	cout << "---> x : " << x.to_string() << endl;
	cout << "Give y : "; getline(cin,s,'\n');
	Big_Nat y(s);
	cout << "---> y : " << y.to_string() << endl;
	Big_Nat z = x + y;   //this is where I am stuck..
	cout << " x + y : " << z.to_string() << endl;
	return 0;
}
After a bit of research, it seems that I need to add:

Big_Nat & operator+(const Big_Nat &rhs);

into the public section of my Big_Nat class. Is this correct? Also, what would I need to do to the implementation file so that it works? Any help at all will be appreciated.
You shouldn't return a reference to a local variable, and you can operate with const objects
Big_Nat operator+(const Big_Nat &rhs) const;

Just implement a kinder garden arithmetic (sum digits from right to left, and keep a carry)
That seems to be much easier said than done. Is there a way to overload the operator+ so I can add the two numbers, which are of type Big_Nat? I have been researching for a long time, and I just can't seem to figure it out...
Well, first of all you'll want a copy constructor and an operator= function.

You can read all about overloading operators here:
http://www.cplusplus.com/doc/tutorial/classes2/

It may be confusing at first, but hey, that's what forums are for ;)
Last edited on
You haven't got any pointers in your class. The default copy constructor an operator= should work.
1
2
3
aux = this->vec[K] + b.vec[K] + carry;  //aux will have 9 digits at most
c.vec[K] = /*last 8 digits of aux */;
carry = /* 1 or 0  */;
You need to handle the special case where you still have carry, but you are out of digits.
In general, for a user-defined type T, consider implementing operator+ as a nonmember (non-friend) and in terms of operator+=. For example:
1
2
3
4
5
6
const T operator+( const T & lhs, const T & rhs )
{
    T t( lhs );
    t += rhs;
    return t;
}

Non-friends do not compromise encapsulation and nonmembers provide associativity. The return is by value, such that the arguments remain unchanged, and constant, to prevent it from being used as an lvalue.

Hope this helps.
Last edited on
In general, for a user-defined type T, consider implementing operator+ as a nonmember (non-friend) and in terms of operator+=


Depending on usage, there will be times where we need to have friend function. E.g I allow int + MyClass in this order and also MyClass + int in this order too.

If using non-friend function, may I know how to build logic like int + MyClass ? I.e the int variable is on the lhs of MyClass.
If addition is commutative (lhs+rhs) == (rhs+lhs). You can just make a wrapper.
Or if you consider that an int can be treat as an object of your class, make a constructor. (like in strings).

You can still avoid friends, if you provide methods in your class
If you have operator+( const T& lhs, int rhs ) defined, then

1
2
T operator+( int lhs, const T& rhs )
    { return rhs + lhs; }


BTW, boost has already solved all these problems. Consider using boost::operators
to generate all these. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <boost/operators.hpp>

class MyBigInt : private boost::ordered_euclidean_ring_operators<MyBigInt>,
    boost::ordered_euclidean_ring_operators<MyBigInt, int >
{
    friend bool operator==( const MyBigInt& lhs, const MyBigInt& rhs );
    friend bool operator<( const MyBigInt& lhs, const MyBigInt& rhs );
    MyBigInt& operator+=( const MyBigInt& rhs );
    MyBigInt& operator-=( const MyBigInt& rhs );
    MyBigInt& operator*=( const MyBigInt& rhs );
    MyBigInt& operator/=( const MyBigInt& rhs );

    friend bool operator==( const MyBigInt& lhs, int rhs );
    friend bool operator<( const MyBigInt& lhs, int rhs );
    MyBigInt& operator+=( int rhs );
    MyBigInt& operator-=( int rhs );
    MyBigInt& operator*=( int rhs );
    MyBigInt& operator/=( int rhs );    
};


(Note that private inheritance is preferred because boost declares all the remaining functions
as friends, and you probably don't want people doing polymorphic upcasts to
boost::ordered_euclidean_ring_operators<MyBigInt> and such).

If you implement the above methods, then you should get all other permutations for free
(through the inheritance) that allow operation on two MyBigInts or a MyBigInt and an int.
Topic archived. No new replies allowed.