define your own class that will represent a fraction in your program

Pages: 12
Could someone highlight the parts I need to change

I already did that in my post on Nov 27, 2014 at 11:11am. Read the post again. Here is one last hint: Answer and Answer1 are DIFFERENT VARIABLES. They are NOT THE SAME.
Last edited on
correct, I did that. I changed all of these just to answer and I get an error.
Did you fix the bug in gcd()? A previous version assumed that x>y.

You might want to post your full code as it currently exists and tell us what specific error you are getting.
So I dont think my answers are correct. Example: I enter -1/3 as fraction. and the (-) subtraction.

I get 1/10 - -1/3 = -2/3 which is also -0.666667

The correct answer should be 1/10 - -1/3 = 13/30 which is also 0.433333

I probably get other answers wrong as well.

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
151
152
153
154
155
156
157
158
#include <iostream>
#include <algorithm> // for the my gcd function which uses min
using namespace std;

class fraction
{
public:
	fraction(); // constructor that defines a default fraction of 0/1 
	fraction(int x, int y); // constructor that defines a fraction n/d

	void input(); // read a fraction of the form x/y from the user
	void output(); // print the fraction in the form x/y to the screen
	double toDecimal(); // returns the decimal value of the member fraction

	fraction add(fraction& frac2); // adds second to the member fraction and returns the result in a new fraction
	fraction subtract(fraction frac2); // subtracts second from the member fraction and returns the result in a new fraction
	fraction multiply(fraction frac2); // multiplies second and the member fraction and returns the result in a new fraction
	fraction divide(fraction frac2); // divides the member fraction by second and returns the result in a new fraction

private:
	int num;
	int denom;
	void reduce();
	int gcd(int x, int y);
};

int main()
{
	fraction frac1; // to be set by user
	fraction frac2, answer; // default constructed, and the answer to the operations
	char o;
	cout << "Please enter a fraction in x/y form: ";
	frac1.input();
	cout << "Please enter an operation (+, -, *, /): ";
	cin >> o;

	if (o == '+') { answer = frac1.add(frac2); }
	if (o == '-') { answer = frac1.subtract(frac2); }
	if (o == '*') { answer = frac1.multiply(frac2); }
	if (o == '/') { answer = frac1.divide(frac2); }

	frac2.output();
	cout << ' ' << o << ' ';
	frac1.output();
	cout << " = ";
	answer.output();
	cout << " which is also " << answer.toDecimal() << endl;
	

	return 0;
}
void fraction::input()
{
	char trash;
	cin >> num >> trash >> denom; //memory used to enter the divide symbol in the fraction
	if (denom == 0)
	{
		cout << "Can't have a zero denominator!" << endl;
		exit (1);
	}
}
void fraction::output()
{
	cout << num << "/" << denom;
}
void fraction::reduce()
{
	//int factor;
	//int answer1;
	//int gcd(int x, int y);
	
	int answer = gcd(num, denom);
	//factor = denom / num;
	num /= answer;
	denom /= answer;
}
int fraction::gcd(int x, int y)
{
	if (y == 0)
	{
		return x;
	}
	return gcd (y, x % y);
}
double fraction::toDecimal()
{
	return num / (denom * 1.0);
}
fraction fraction::add(fraction& frac2)	// scope, classname fraction, identifier add function
{
	fraction answer;
	int newDenom;
	int factor;
	if (denom == frac2.denom) {
		answer.num = num + frac2.num;
		answer.denom = denom;
	}
	else {
		newDenom = gcd(denom, frac2.denom);
		factor = newDenom / denom;
		if (num / factor != 1)
			num *= factor;
		if (frac2.num / factor != 1)
			frac2.num *= factor;
		denom = newDenom;
		frac2.denom = newDenom;
		answer.num = num + frac2.num;
		answer.denom = denom;
	}
	reduce();
	frac2.reduce();
	answer.reduce();
	return answer;
}
fraction fraction::subtract(fraction frac2)
{
	fraction answer;
	if (denom == frac2.denom) {
		answer.num = num - frac2.num;
		answer.denom = denom;
	}
	else {
		gcd(denom, frac2.denom);
		if (denom == frac2.denom) {
			cout << "gcd failed" << endl;
		}
		answer.num = num - frac2.num;
		answer.denom = denom;
	}
	answer.reduce();
	return answer;
}
fraction fraction::multiply(fraction frac2)
{
	fraction answer;
	answer.num = (num * frac2.num);
	answer.denom = (denom * frac2.denom);
	answer.reduce();
	return answer;
}
fraction fraction::divide(fraction frac2)
{
	fraction answer;
	answer.num = (num * frac2.denom);
	answer.denom = (denom * frac2.num);
	answer.reduce();
	return answer;
}
fraction::fraction(int x, int y)
{
	num = x;
	denom = y;
}
fraction::fraction()
{
	num = 1;
	denom = 10;
}

divide, subtract, and Add dont calculate correctly...
You've made add() too complicated. To add a/b and c/d, put both fractions over a common denomimator: ad/bd + bc/bd. So the answer is (ad+bc)/bd. So the code is:
- create new fraction: (ad+bc)/bd
- reduce it
- return it

In particular, do NOT change the current fraction and do NOT change the parameter frac2. You can tell the compiler to enforce this by declaring the add method as fraction add(const fraction &frac2) const;.
Divide may appear wrong because you're printing the arguments out in the wrong order at line 42 & 44. frac1.divide(frac2) computes frac1 / frac2, not frac2 / frac1
You're making the math over-complicated, and apt to return non-integer numerators and denominators.

For example, adding two fractions:

1
2
n1	+	n2	= (n1 *d2 + n2 * d1)
d1		d2	     d1 * d2


can be generically expressed this way:

1
2
int NewNum  = num1 * denom2 + num2 * denom1;
int NewDenom = denom1 * denom2;


Your usage should be something along the lines of :

num * frac2.denom. . . etc.

Subtraction is the same concept, just changing sign from + to -.

However, if you make your parameterized constructor this way:

1
2
3
4
5
6
fraction::fraction(int x, int y)
{
	num = x;
	denom = y;
	reduce();
}


and then in your math calculations do:

1
2
3
fraction fraction::add(fraction& frac2)
fraction answer (num * frac2.denom + denom * frac2.num, denom * frac2.denom)
// same idea for all four math functions 


you won't have to call reduce() - it will run whenever you create a fraction object.

reduce() should account for negative numerator and/or denominator:

1
2
3
4
5
6
7
8
9
10
void fraction::reduce()
{
	// right here you should include a plus/minus determination
	//remember it and apply after gcd(. . .)

	int answer = gcd(num, denom);
	//factor = denom / num;
	num /= answer;
	denom /= answer;
}


output() should account for improper fractions (num> denom)

1
2
3
4
5
void fraction::output()
{
	if(num > denom) cout << num/denom << " ";
	cout << num % denom << "/" << denom;
}



dhayden20:
Did you fix the bug in gcd()? A previous version assumed that x>y.

Actually, since x and y are reversed each iteration of reduce, it is only necesary to ensure that both are positive integers.
Last edited on
I think my only issue now is that when I enter a negative number such as -1/3 and do subtraction or addition, i get the wrong answer. How do i fix this?
Thank you

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
151
152
153
154
155
156
157
158
159
160
161
162
#include <iostream>
#include <algorithm> // for the my gcd function which uses min
using namespace std;

class fraction
{
public:
	fraction(); // constructor that defines a default fraction of 0/1 
	fraction(int x, int y); // constructor that defines a fraction n/d

	void input(); // read a fraction of the form x/y from the user
	void output(); // print the fraction in the form x/y to the screen
	double toDecimal(); // returns the decimal value of the member fraction

	fraction add(fraction& frac2); // adds second to the member fraction and returns the result in a new fraction
	fraction subtract(fraction frac2); // subtracts second from the member fraction and returns the result in a new fraction
	fraction multiply(fraction frac2); // multiplies second and the member fraction and returns the result in a new fraction
	fraction divide(fraction frac2); // divides the member fraction by second and returns the result in a new fraction

private:
	int num;
	int denom;
	void reduce();
	int gcd(int x, int y);
};

int main()
{
	fraction frac1; // to be set by user
	fraction frac2, answer; // default constructed, and the answer to the operations
	char o;
	cout << "Please enter a fraction in x/y form: ";
	frac1.input();
	cout << "Please enter an operation (+, -, *, /): ";
	cin >> o;

	if (o == '+') { answer = frac2.add(frac1); }
	else if (o == '-') { answer = frac2.subtract(frac1); }
	else if (o == '*') { answer = frac2.multiply(frac1); }
	else if (o == '/') { answer = frac2.divide(frac1); }
	else
	{
		cout << "This is not a valid operation!" << endl;
		return 0;
	}
	frac2.output();
	cout << ' ' << o << ' ';
	frac1.output();
	cout << " = ";
	answer.output();
	cout << " which is also " << answer.toDecimal() << endl;
	

	return 0;
}
void fraction::input()
{
	char trash;
	cin >> num >> trash >> denom; //memory used to enter the divide symbol in the fraction, roomate helped me look this up.
	if (denom == 0)
	{
		cout << "Can't have a zero denominator!" << endl;
		exit (1);
	}
}
void fraction::output()
{
	cout << num << "/" << denom;
}
void fraction::reduce()
{
	int answer = gcd(num, denom);
	num /= answer;
	denom /= answer;
}
int fraction::gcd(int x, int y)
{
	if (y == 0)
	{
		return x;
	}
	return gcd (y, x % y);
}
double fraction::toDecimal()
{
	return num / (denom * 1.0);
}
fraction fraction::add(fraction& frac2)	// scope, classname fraction, identifier add function
{
	fraction answer;
	int newDenom;
	int factor;

	if (num == 0 || frac2.num == 0)
		return *this; // friend suggested to check for fraction which equals 0
	else if (denom == frac2.denom) {
		answer.num = num + frac2.num;
		answer.denom = denom;
	}
	else {
		newDenom = gcd(denom, frac2.denom);
		factor = denom / newDenom;
		if (num / factor != 1)
			num *= factor;
		if (frac2.num / factor != 1)
			frac2.num *= factor;
		denom = newDenom;
		frac2.denom = newDenom;
		answer.num = num + frac2.num;
		answer.denom = denom;
	}
	reduce();
	frac2.reduce();
	answer.reduce();
	return answer;
}
fraction fraction::subtract(fraction frac2)
{
	fraction answer;
	if (num == 0 || frac2.num == 0)
		return *this; // friend suggested to check for fraction which equals 0
	else if (denom == frac2.denom) {
		answer.num = num - frac2.num;
		answer.denom = denom;
	}
	else {
		gcd(denom, frac2.denom);
		if (denom == frac2.denom) {
			cout << "gcd failed" << endl;
		}
		answer.num = num - frac2.num;
		answer.denom = denom;
	}
	answer.reduce();
	return answer;
}
fraction fraction::multiply(fraction frac2)
{
	fraction answer;
	answer.num = (num * frac2.num);
	answer.denom = (denom * frac2.denom);
	answer.reduce();
	return answer;
}
fraction fraction::divide(fraction frac2)
{
	fraction answer;
	answer.num = (num * frac2.denom);
	answer.denom = (denom * frac2.num);
	answer.reduce();
	return answer;
}
fraction::fraction(int x, int y)
{
	num = x;
	denom = y;
}
fraction::fraction()
{
	num = 1;
	denom = 10;
}
Please re-read http://www.cplusplus.com/forum/beginner/148764/2/#msg781821

Also, repeating part of http://www.cplusplus.com/forum/beginner/148764/#msg779251:
Inside reduce, I recommend that you also normalize numbers like -4/-5 to 4/5, and 4/-5 to -4/5. Be sure to handle the case where denominator is zero, and where both numerator and denominator are zero.


Or you go with http://www.cplusplus.com/forum/beginner/148764/2/#msg781840

The advice in these posts will fix the problems.
This whole section of code needs to go away, along with the almost identical code for subtraction. Most of it doesn't do anything, does stuff wrong, and is way overthought and complex.

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
fraction fraction::add(fraction& frac2)	// scope, classname fraction, identifier add function
{
	fraction answer;
	int newDenom;
	int factor;

	if (num == 0 || frac2.num == 0) 
		//void reduce () can deal with this situation; unnecessary
		// also, you are returning the same fraction for each case:
		// 3/4 + 0/2 = 3/4: return *this  returns 3/4.
		// 0/2 + 3/4 = 3/4: return *this returns 0/2.			
		return *this; // friend suggested to check for fraction which equals 0
	else if (denom == frac2.denom) { //void reduce() can deal with this also
		answer.num = num + frac2.num;
		answer.denom = denom;
	}
	else {
		newDenom = gcd(denom, frac2.denom); // why gcd of the denominators?
		factor = denom / newDenom; // most of the time newDenom is 1
					// this whole routine is completely unnecessary
		if (num / factor != 1)
			num *= factor;
		if (frac2.num / factor != 1)
			frac2.num *= factor;
		denom = newDenom;
		frac2.denom = newDenom;
		answer.num = num + frac2.num;
		answer.denom = denom;
	}
	reduce();
	frac2.reduce();
	answer.reduce();
	return answer;
}


Two lines for the math, then reduce however you want:

1
2
3
newNum = num1*den2+num2*den1;
newDen = den1 * den2;
reduce() // if you even need to do this here - your constructor can do it for you. 


For subtraction:
1
2
3
newNum = num1*den2-num2*den1;
newDen = den1 * den2;
reduce()


Your professor included these for a reason:
Finally, the class should define at least one private member function:
fraction(int n, int d); // constructor that defines a fraction n/d


This constructor

1
2
3
4
5
6
7
fraction::fraction(int n, int d)
{
      numerator = n;
      denominator = d;
      if (denominator == 0) // some fault message here. . .;
      else reduce();
}


will do reduce() every time you create a new fraction object,
using numerator math for n, denominator math for d:
1
2
fraction temp(num1*num2, den1*den2); // for multiplication. . .etc. for other actions.
return temp;


You could declare and use temporary int values for the math, but it isn't necessary.

void reduce(); // reduce the member fraction to simplest terms, which should be done automatically any time that the value of the member fraction changes


void reduce() is where you can account for division-by-zero, correct sign for the new fraction, and if you want, extract and store the whole number part (though not necessary; void output() can do that for you.
Topic archived. No new replies allowed.
Pages: 12