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

Pages: 12
Ive started this assignment. Not sure what to do from here:


Write a class definition for a fraction class. That is, define your own class that will represent a fraction in your program. Each object of type fraction represents a single fraction. That means that the class has two member variables that should be private: the numerator and the denominator of the fraction. The class also must have the following public member functions:
fraction(); // constructor that defines a default fraction of 0/1
fraction(int n, int d); // constructor that defines a fraction n/d
fraction plus(fraction second); // adds second to the member fraction and returns the result in a new fraction
fraction minus(fraction second); // subtracts second from the member fraction and returns the result in a new fraction
fraction times(fraction second); // multiplies second and the member fraction and returns the result in a new fraction
fraction divides(fraction second); // divides the member fraction by second and returns the result in a new fraction
double toDecimal(); // returns the decimal value of the member fraction
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

Finally, the class should define at least one private member function:
void reduce(); // reduce the member fraction to simplest terms, which should be done automatically any time that the value of the member fraction changes


Note that the reduce() function should use Euclid’s method (as we did in Lab 7) to find the greatest common divisor of the numerator and denominator. You may do that directly in the reduce() function, or you may add another private member function to the class just to calculate the GCD. The latter is strongly recommended.

You will also have to write a driver program to test your fraction class. Be sure that you test all the member functions for correctness in the driver. That is, your driver should allow you (and the instructor!) to verify that each of the member functions in your class works correctly.

Here is my code as of now:

#include <iostream>
using namespace std;

void add(char o, int frac1);
void subtract(char& o, int& frac1);
void multiply(char& o, int& frac1);
void divide(char& o, int& frac1);

class fraction
{
public:
void plus_equal(fraction frac2)
{

}
void input()
{
cin >> num >> denom;
}
void output()
{
cout << num << "/" << denom << endl;
}
private:
int num;
int denom;
};

int main()
{
int frac1;
char o = '*';

cout << "Please enter a fraction in x/y form: ";
cin >> frac1;
cout << "Please enter an operation (+, -, *, /): ";
cin >> o;

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

fraction frac1, frac2;

cout << "Please enter a fraction in x/y form: ";
frac1.input();
frac1.output();
cout << "Enter a fraction: ";
frac2.input();
frac2.output();
frac1.plus_equal(frac2);
return 0;
}
Can you please format your code using the code format tags.

You're on the right track, in that, your class holds a numerator and denominator.

Where it falls down is in its interface. Perhaps if you try make it look more like a regular number, it'll guide your design.

I don't know how much C++ you've done, but there are a few tricks you can use to make it work more seamlessly with I/O. Additionally, operator overloading will allow you to use +, -, /, * in the normal way for your class.

Let's say, we wanted you program to look like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int main()
{
    fraction f1, f2;    // default constructor
    std::cout << "Please enter a fraction in the form x / y: ";
    std::cin >> f1;    // stream in
    std::cout << "Please enter another fraction in the form x / y: ";
    std::cin >> f2;

    char operation;
    std::cout << "Please enter an operation (+, -, /, *): ";
    std::cin >> operation;

    fraction f3;
    switch (operation)
    {
    case '+':  f3 = f1 + f2; break;    // overload +
    case '-':  f3 = f1 - f2; break;    // overload -
    case '*':  f3 = f1 * f2; break;    // overload *
    case '/':  f3 = f1 / f2; break;    // overload /
    }
    std::cout << "Result is: " << f3 << std::endl;    // stream out
}
What would class fraction need to look like?
So my setup should look similar to your for main()?

Not sure about the class fraction look.
So my setup should look similar to your for main()?
No, not really.

The design of class fraction seems to be headed down the wrong path. I'm trying to help you develop a method to improve your design. That method is to not think solely on how the class works, but also think about how it might be used.

An analogy is, if you build your brand new electric car, but provide dials to control acceleration and breaking rather than pedals, and slide controls insead of a steering wheel, your otherwise potential customers will loose interest, even though that's those aren't unusual controls on a radio.

Similarly, a user of a rational number class would not expect to place values in with an input() method, or get results with an output() method.
Last edited on
im suppost to have the parts:
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
im suppost to have the parts:
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
Ok, well I guess you have to start somewhere.

So what's the problem?

#include <iostream>
using namespace std;

void add(char o, int frac1);
void subtract(char& o, int& frac1);
void multiply(char& o, int& frac1);
void divide(char& o, int& frac1);

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
{
int x, y;
cin >> x >> y;
}
void plus(fraction frac2) // adds second to the member fraction and returns the result in a new fraction
{

}
fraction minus(fraction frac2) // subtracts second from the member fraction and returns the result in a new fraction
{

}
fraction times(fraction frac2) // multiplies second and the member fraction and returns the result in a new fraction
{

}
fraction divides(fraction frac2) // divides the member fraction by second and returns the result in a new fraction
{

}

void output() // print the fraction in the form x/y to the screen
{
cout << num << "/" << denom << endl;
}
double toDecimal(); // returns the decimal value of the member fraction
{

}
private:
int num;
int denom;
void reduce() // reduce the member fraction to simplest terms, which should be done automatically any time that the value of the member fraction changes
{

}
};

int main()
{
int frac1;
char o = '*';

cout << "Please enter a fraction in x/y form: ";
cin >> frac1;
cout << "Please enter an operation (+, -, *, /): ";
cin >> o;

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

fraction frac1, frac2;

cout << "Please enter a fraction in x/y form: ";
frac1.input();
frac1.output();
cout << "Enter a fraction: ";
frac2.input();
frac2.output();
frac1.plus_equal(frac2);
return 0;
}

This is what I got, hopefully I formatted this right.
By the parameters given, it looks like you'll need something like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int main()
{
    fraction f1, f2;    // default constructor
    f1.input();

    char operation;
    std::cout << "Please enter an operation (+, -, /, *): ";
    std::cin >> operation;

    f2.input();


    fraction f3;
    switch (operation)
    {
    case '+':  f3 = f1 + f2; break;    // overload +
    case '-':  f3 = f1 - f2; break;    // overload -
    case '*':  f3 = f1 * f2; break;    // overload *
    case '/':  f3 = f1 / f2; break;    // overload
    }
   
}


The double toDecimal() must be intended as a utility - maybe part of the menu as choice "D," and add case 'D'; f1.toDecimal; and toDecimal would call output() automatically? Each fraction object probably need to call output() for each change in its own value.
Although kbw and PCrumley48 are recommending better designs, that isn't what the assignment calls for. UNfortunately, your class should do what the assignment asks for. Maybe a future assignment will convert the plus(), minus() times() and divides() functions to operators.

Start by writing the two constructors and the output() function. Create a main() program that tests those out.

Next write toDecimal() and input(). Add code to test it out. By the way, your current input() function isn't right because it doesn't handle the '/' that separates the two values.

Then write times() and divides(). Add code to main to test these out also. Consider error cases: What should happen if you divide by zero?

Next write plus() and minus() and add code to main() to test these.

Now write reduce(). Take the prof's advice and write a separate GCD() function. 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.
Im getting there now!! I need help looking at my functions for add, subtract, mult, divide. They are not producing the correct calculation.

When I enter a fraction such as 3/4 and + , the debugger should write out 1/10 + 3/4 =

#include <iostream>
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(); // adds second to the member fraction and returns the result in a new fraction
fraction subtract(); // subtracts second from the member fraction and returns the result in a new fraction
fraction multiply(); // multiplies second and the member fraction and returns the result in a new fraction
fraction divide(); // divides the member fraction by second and returns the result in a new fraction

private:
int num;
int denom;
fraction reduce();
int gcd(int A, int B);
};

int main()
{
fraction frac1, answer;
fraction frac2(1, 10);
char o;
cout << "Please enter a fraction in x/y form: ";
frac1.input();
//Can't have a zero denominator!
//return 1;
cout << "Please enter an operation (+, -, *, /): ";
cin >> o;

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

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

return 0;
}
void fraction::input()
{
char trash;
cin >> num >> trash >> denom; //memory used to enter the divide symbol in the fraction
}
void fraction::output()
{
cout << num << "/" << denom;
}
fraction fraction::reduce()
{

num = num / denom;
int newDenom = gcd(denom, num % denom);
fraction answer;
answer.num = num;
answer.denom = newDenom;
return answer;
}
int fraction::gcd(int A, int B)
{
if (B == 0)
{
return A;
}
return gcd(B, A% B);
}
double fraction::toDecimal()
{
return num / denom;
}

fraction fraction::add()
{
num = ((num * 10) + (denom * 1));
denom = denom * 10;
fraction answer;
answer.num = num;
answer.denom = denom;
return answer;
}

fraction fraction::subtract()
{
num = ((num * 10) - (denom * 1));
denom = denom * 10;
fraction answer;
answer.num = num;
answer.denom = denom;
return answer;
}

fraction fraction::multiply()
{
num = (num * 1);
denom = (denom * 10);
fraction answer;
answer.num = num;
answer.denom = denom;
return answer;
}

fraction fraction::divide()
{
num = (num * 10);
denom = (denom * 1);
fraction answer;
answer.num = num;
answer.denom = denom;
return answer;
}
fraction::fraction(int x, int y)
{
num = x;
denom = y;
}
fraction::fraction()
{
num = 1;
denom = 10;
}
dhayden: You're right - I overlooked the need for individual plus/minus. . .sorry. . . :(
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int main()
{
    fraction f1, f2;    // default constructor
    f1.input();

    char operation;
    std::cout << "Please enter an operation (+, -, /, *): ";
    std::cin >> operation;

    f2.input();


    fraction f3;
    switch (operation)
    {
    case '+':  f3 = f1.plus(f2); break;
    case '-':  f3 = f1.minus(f2); break;
    case '*':  f3 = f1.times(f2); break;
    case '/':  f3 = f1.divides(f2); break;
    }
   
}


gmac: Please, PLEASE use code tags ( button <> to the right) when you input your code:

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
[code]#include <iostream>
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(); // adds second to the member fraction and returns the result in a new fraction
	fraction subtract(); // subtracts second from the member fraction and returns the result in a new fraction
	fraction multiply(); // multiplies second and the member fraction and returns the result in a new fraction
	fraction divide(); // divides the member fraction by second and returns the result in a new fraction

private:
	int num;
	int denom;
	fraction reduce();
	int gcd(int A, int B);
};

int main()
{
	fraction frac1, answer;
	fraction frac2(1, 10);
	char o;
	cout << "Please enter a fraction in x/y form: ";
	frac1.input();
		//Can't have a zero denominator!
		//return 1;
	cout << "Please enter an operation (+, -, *, /): ";
	cin >> o;

 	// you're getting erratic answers because you aren't using frac1 values
	// try using something like 
	// if (o == '+') { answer = frac1.add(frac2);. . etc. }

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


	frac2.output();
	cout << ' ' << o << ' ';
	frac1.output();
	cout << " = ";
	answer.output();
	cout << " which is also "; //if toDecimal is returning a double, leave out ; , use << 
	answer.toDecimal();

	return 0;
}

void fraction::input()
{
	char trash;
	cin >> num >> trash >> denom; //memory used to enter the divide symbol in the fraction
}

void fraction::output()
{
	cout << num << "/" << denom;
}

fraction fraction::reduce() // this function can act on the member values
//void fraction::reduce()
{
	num = num / denom;
	int newDenom = gcd(denom, num % denom);
	fraction answer; // don't need this
	answer.num = num; // can act on the member value num
	answer.denom = newDenom; //can act on the member value denom
	return answer; // not needed
}

int fraction::gcd(int A, int B)
{
	if (B == 0)
	{
		return A;
	}
	return gcd(B, A% B);
}

double fraction::toDecimal()
{
	return num / denom;
}

fraction fraction::add()  // if you accept a fraction as a parameter you can do "answer = fract1.add(fract2)" in main
//fraction fraction::add(fraction second)
{
	num = ((num * 10) + (denom * 1));
	denom = denom * 10;
	fraction answer;
	answer.num = num;
	answer.denom = denom;
	return answer;
}

fraction fraction::subtract()
{
	num = ((num * 10) - (denom * 1));
	denom = denom * 10;
	fraction answer;
	answer.num = num;
	answer.denom = denom;
	return answer;
}

fraction fraction::multiply()
{
	num = (num * 1);
	denom = (denom * 10);
	fraction answer;
	answer.num = num;
	answer.denom = denom;
	return answer;
}

fraction fraction::divide()
{
	num = (num * 10);
	denom = (denom * 1);
	fraction answer;
	answer.num = num;
	answer.denom = denom;
	return answer;
}

fraction::fraction(int x, int y)  // this constructor could call reduce() and output(). . . 
{
	num = x;
	denom = y;
//	reduce();
//	output();
}

fraction::fraction()
{
	num = 1; //your default constructor is to create a fraction 0/1. . .right?
	denom = 10;
}
[/code]
Look closely at the definition of plus in the assignment:
fraction plus(fraction second); // adds second to the member fraction and returns the result in a new fraction
You need to code it like this. It takes a fraction as a parameter and returns a new fraction as a result.

So what is this new fraction? Sit down with a pencil and paper. Figure out what a/b + c/d is in terms of a, b, c, and d. You'll need to do the same for subtraction, multiplication and division.

Im having a hard time getting my reduce and gcd functions to work together.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void fraction::reduce()
{
	//int factor;
	int answer1;
	int gcd(int x, int y);
	num = x;
	denom = y;
	answer1 = gcd(x, y);
	//factor = denom / num;
	num /= answer1;
	denom /= answer1;
}
int fraction::gcd(int x, int y)
{
	if (y == 0)
	{
		return x;
	}
	return gcd (y, x % y);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void fraction::reduce()
{
	int answer1; //can combine this declaration with call to gcd(x,y)
	int gcd(int x, int y); 
		// don't need this declaration
		// c++ is going to look for a function for this prototype
		// my compiler complains about an unresolved external
	num = x; 	// don't need x or y
	denom = y;
	answer1 = gcd(x, y); // use "int answer = gcd( num, denom );"

	num /= answer1;
	denom /= answer1;
}
int fraction::gcd(int x, int y)
{
	if (y == 0)
	{
		return x;
	}
	return gcd (y, x % y);
}
I fixed most of what you said PCrumley48.
I dont know where to combine the int answer1, in the reduce() or the gcd() below?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void fraction::reduce()
{
	//int factor;
	int answer1;
	//int gcd(int x, int y);
	
	int answer = gcd(num, denom);
	//factor = denom / num;
	num /= answer1;
	denom /= answer1;
}
int fraction::gcd(int x, int y)
{
	if (y == 0)
	{
		return x;
	}
	return gcd (y, x % y);
}
Check your reduce() code carefully. Here it is with the variable names highlighted:
1
2
3
4
5
6
7
8
9
10
11
void fraction::reduce()
{
	//int factor;
	int answer1;
	//int gcd(int x, int y);
	
	int answer = gcd(num, denom);
	//factor = denom / num;
	num /= answer1;
	denom /= answer1;
}
You also have a small bug in gcd(). gcd(4,6) returns 6.
Last edited on
I'm sorry, i'm not good at coding. Im still confused whats wrong...
You set answer to the gcd(), but you don't use it. Instead, you use answer1, which is a completely different variable and hasn't been initialized.

The bug in gcd is at line 18. You assume that x<=y
Im still not understanding this? Can someone help?
Could someone highlight the parts I need to change and what to change it to? Sorry I dont understand...
Pages: 12