Problems with const

May 31, 2014 at 4:23pm
Hello I have written some code and I wanted to avoid that the parameters are getting copied every time the function gets called because that operation is quite time expensive. So I used BigInt operator + (const BigInt & a,const BigInt & b) {
(BigInt is a class with two objects like this) :
1
2
bool negative;
vector <int> digits;


Now I have written my code like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
BigInt operator + (const BigInt & a,const BigInt & b) {
	if (b.negative==a.negative) {
		BigInt res;
		//...... irrelevant
		
		return res;
	} else {
		if (a.negative) {
			//a.negative=false;
			return b-a;
		} else {
			//b.negative=false;
			return a-b;
		}
	}
}


Now I have a problem because I need to perform the subtraction but before that I should have the negative changed but I can't do this anymore because it is const. No matter what I don't want to make a new BigInt and copy all the elements to it because if I do that then my code is about 50% slower...

If anything is not clear feel free to ask me.
Thanks in advance
Jannes
Last edited on May 31, 2014 at 4:24pm
May 31, 2014 at 4:49pm
If you have operator-() defined, you could try doing something like
1
2
3
4
5
if (a.negative) {
    return b - (-a);
} else {
    return a - (-b);
}
May 31, 2014 at 5:18pm
But BigInt operator-() const; would return a copy of 'a'.

You may have private subtract/add operations that do not take into account the sign of the operands, then you have operator-(a,b) as a wrapper that will correctly determine the sign of the result and call the appropriate function.
Jun 1, 2014 at 6:37pm
They should take into account the sign of the operands because it is quite easy to see that 5+3 and 5+(-3) require a different function to work.

EDIT: I think I know what you mean. I'll make a sub function and an add function that don't look to the signs. and then depending on the sign I will call the correct function without altering the signs.

EDIT2:
This became my final code and it works now :) (without copying anything) thanks to you ne555.

I would be very grateful if anyone could check my code for any possible errors. Maybe I added two values when they should be subtracted or anything like that. Thanks in advance

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
void add (BigInt & res,const BigInt &a,const BigInt &b) {
	//value of res is altered.
}

void sub(BigInt & res,const BigInt & a,const BigInt & b) {
	//value of res is altered.
}

BigInt operator + (const BigInt & a,const BigInt & b) {
	BigInt res;
	res.digits.reserve(a.digits.size()+2);

	if (b.negative==a.negative) {
		if (b.digits.size()>a.digits.size()) {
			add(res,b,a);
		} else {
			add(res,a,b);
		}
	} else if (a.negative) {
		if (b>a) {
			sub(res,b,a);
			res.negative=false;
		} else {
			sub(res,a,b);
			res.negative=true;
		}
	} else {
		if (a>b) {
			sub(res,a,b);
			res.negative=false;
		} else {
			sub(res,b,a);
			res.negative=true;
		}
	}
	return res;
}

BigInt operator - (const BigInt & a,const BigInt & b) {
	BigInt res;
	res.digits.reserve(a.digits.size()+2);

	if (!b.negative && !a.negative) {
		if (a>b) {
			sub(res,a,b);
		} else {
			sub(res,b,a);
			res.negative=true;
		}
	} else if (b.negative && a.negative) {
		if (b>a) {
			sub(res,b,a);
		} else {
			sub(res,a,b);
			res.negative=true;
		}
	} else if (b.negative) {
		add(res,a,b);
	} else {
		add(res,a,b);
		res.negative=true;
	}

	return res;
}
Last edited on Jun 1, 2014 at 7:52pm
Jun 1, 2014 at 9:09pm
1
2
//res.digits.reserve(a.digits.size()+2);
res.digits.reserve( std::max(a.digits.size(), b.digits.size()) + 1 );


1
2
else if (a.negative) {
		if (b>a) //I suppose that you do take into account the sign in operator<, so this is a tautology 


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
BigInt operator + (const BigInt & a,const BigInt & b) {
	BigInt res;
	res.digits.reserve(a.digits.size()+2);

	if (b.negative==a.negative) { //-|a| + -|b| = -( |a|+|b| )
		if (b.digits.size()>a.digits.size()) {
			add(res,b,a);
		} else {
			add(res,a,b);
		}
	} else if (a.negative) { //-|a| + |b| = |b| - |a|
		if (b>a) {
			sub(res,b,a);
			res.negative=false;
		} else {
			sub(res,a,b);
			res.negative=true;
		}
	} else { // |a| + -|b| = |a|-|b|    or    |a|+|b| = |a|+|b|
		if (a>b) {
			sub(res,a,b);
			res.negative=false;
		} else {
			sub(res,b,a);
			res.negative=true;
		}
	}
	return res;
}
you missed the case were 'a' and 'b' are positive.
That could be done as
1
2
3
4
if( a.sign == b.sign ){
   add(res, a, b);
   res.sign = a.sign;
}
Last edited on Jun 1, 2014 at 9:10pm
Jun 2, 2014 at 6:03am
Thanks for pointing out the mistakes with the reserve and the tautology :)
The case where a and b are positive is already handled because in my code I had if (b.negative==a.negative) { and if a.negative and b.negative are both false (which means they are both positive) then the equality will return true.
Jun 3, 2014 at 5:17am
that's right, I must have misread it.
However, ¿where do you set the sign of the result?
Topic archived. No new replies allowed.