fractions/mixed numbers

This program should take two inputs (numerator and denominator)
and rewrite the function in simplified form, if numerator>denominator,
it should be rewritten in mixed form, and if the denominator is negative, the - sign should be moved above.
I have a few issues with this program:

Fractions that should not return a mixed number (ex. 4/2), return it anyway (4/2= 2 0/2) instead of just 4/2=2.

in line 26 (divide by zero), I would like to raise an error, but I am not sure if I am doing it right, since anytime I input 0 as the denominator, the whole program blocks.


everytime I obtain the outcome, the program should ask (try again y/n ?) right away, but it doesn't.
Instead I have to type something new and then it exits the command prompt.
I have no idea what is the issue here.


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
 #include "pch.h"
#include <iostream>
#include<algorithm>
#include<exception>

using namespace std;

int gcd_numdem(int a, int b)
{
	int i, gcd;
	a = abs(a);
	b = abs(b);

	for (i = 1; i <= a && i <= b; i++)
	{
		if (a%i == 0 && b%i == 0)
		{
			gcd = i;
		}
		else if (a == 0)
		{
			gcd = 0;
		}
		else if (b == 0)
		{
			throw invalid_argument( "ERROR: cannot divide by zero" );
		}
	}
	return gcd;
}


void num_den(int num, int den)
{
	if ((abs(num) > den) && (den>0) && (gcd_numdem(num,den)!=0))
	{
		cout << (num / gcd_numdem(num, den)) / (den / gcd_numdem(num, den)) << " "
			<< (num / gcd_numdem(num, den)) % (den / gcd_numdem(num, den)) << "/" <<
			abs(den) / gcd_numdem(num, den) << endl;
	}
	else if ((abs(num) > den)&&(den < 0) && (gcd_numdem(num, den) != 0))
	{
		cout <<"-"<<( num / gcd_numdem(num, den)) / (den / gcd_numdem(num, den)) << " "
			<< (num / gcd_numdem(num, den)) % (den / gcd_numdem(num, den)) << "/" <<
			abs(den) / gcd_numdem(num, den) << endl;
	}
	else
	{
		cout << num / gcd_numdem(num, den) << "/" << den / gcd_numdem(num, den) << endl;
	}
}

int main()
{
	char answer;
	do {
		int x, y;
		cout << "enter numerator" << endl;
		cin >> x;
		cout << "enter denominator" << endl;
		cin >> y;
		
		num_den(x, y);

		cin >> answer;
		cout << "try again(Y/N)?" << endl;
	} while (answer == 'Y' || answer == 'y');

		return 0;

}
cin >> answer;
cout << "try again(Y/N)?" << endl;
} while (answer == 'Y' || answer == 'y');

that says --- get the answer from the user
before asking them the question

reverse the two, and type Y or y when you want to go again.
Last edited on
I reversed the two,
so that's what it looks like now

1
2
3
cin >> answer;
		cout << "try again(Y/N)?" << endl;
	} while (answer == 'y' || answer == 'Y');


but nothing changed.
Also,
any idea about the other issues?
Reverse the cin and cout lines, not the order of the statements in the while condition.

Fractions that should not return a mixed number (ex. 4/2), return it anyway (4/2= 2 0/2) instead of just 4/2=2.

Have a check to see if numerator % denominator == 0, and if so, print numerator / denominator.

If you want to handle the exception you create, you have to catch it in an outer scope.
http://www.cplusplus.com/doc/tutorial/exceptions/

PS: Standard O(log n) gcd formula: https://stackoverflow.com/a/19738969/8690169
Also implemented in the standard library (C++17): https://en.cppreference.com/w/cpp/numeric/gcd
Last edited on
I have been doing some search in how to handle the division by zero case, but is still not working.
This is my new code, everything works as it should but once my input for the denominator is zero, the program still blocks and does not go forward.
Can anyone please correct that specific ''throw error'' line ?

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
#include <iostream>
#include<algorithm>
#include<stdexcept>

using namespace std;

int gcd_numdem(int a, int b)
{
	int i, gcd;
	a = abs(a);
	b = abs(b);

	for (i = 1; i <= a && i <= b; i++)
	{
		if (a%i == 0 && b%i == 0)
		{
			gcd = i;
		}
		else if (a == 0)
		{
			gcd = 0;
		}
		else if (b == 0)
		{
			throw runtime_error("Math error: Attempted to divide by Zero\n");
		}
	}
	return gcd;
}


void num_den(int num, int den)
{
	if ((abs(num) > den) && (den>0) && (num%den!=0))
	{
		cout << (num / gcd_numdem(num, den)) / (den / gcd_numdem(num, den)) << " "
			<< (num / gcd_numdem(num, den)) % (den / gcd_numdem(num, den)) << "/" <<
			abs(den) / gcd_numdem(num, den) << endl;
	}
	else if ((abs(num) > den)&&(den < 0) && (num%den != 0))
	{
		cout <<"-"<<( num / gcd_numdem(num, den)) / (den / gcd_numdem(num, den)) << " "
			<< (num / gcd_numdem(num, den)) % (den / gcd_numdem(num, den)) << "/" <<
			abs(den) / gcd_numdem(num, den) << endl;
	}
	else
	{
		cout << num / gcd_numdem(num, den) << "/" << den / gcd_numdem(num, den) << endl;
	}
}

int main()
{
	char answer;
	do {
		int x, y;
		cout << "enter numerator" << endl;
		cin >> x;
		cout << "enter denominator" << endl;
		cin >> y;
		
		num_den(x, y);

		cout << "try again(Y/N)?" << endl;
		cin >> answer;
	} while (answer == 'Y' || answer == 'y');

		return 0;

}
You'd be better off reducing the number first, and then printing it. This still has some problems related to your gcd() implementation. I'd move the check for divide by zero to num_den() and have gcd_numdem() return 1 if the numbers have no common factors.
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
void num_den(int num, int den)
{
    //
    // Reduce the number
    //

    // 1. If denominator is negative then multiply num and den by -1
    if (den < 0) {
        den = -den;
        num = -num;
    }

    // 2. Remove any common factors
    int gcd = gcd_numdem(num, den);
    num /= gcd;
    den /= gcd;

    //
    // Now move on to printing it
    //

        if (abs(num) > den)
        {
            cout << num / den;
            num = abs(num) % den;       // change num to the remainder
            if (num == 0) {
                cout << '\n';
                return; // if there's no fractional part then you're done
            }
            cout << ' ';
        }

        // If you get there then there's a fractional part to print
        cout << num << '/' << den << '\n';
}

I just want to point at the above vs your code for a sec. Its hard to see at first, but try to get in a habit of recognizing when you are asking the machine to do the same thing over and over.
1
2
3
cout <<"-"<<( num / gcd_numdem(num, den)) / (den / gcd_numdem(num, den)) << " "
			<< (num / gcd_numdem(num, den)) % (den / gcd_numdem(num, den)) << "/" <<
			abs(den) / gcd_numdem(num, den) << endl;


this says get gcd of num, den 5 times. Each one of those runs through a for loop, so if it looped 20 times, you have 100 loops instead of 20, due to calling it over and over. The compiler may or may not be able to fix this but its better all around if you do, as shown above, by storing the result of this gcd once and reusing it. It is easier to read with the clutter removed, and more efficient. With practice you will catch this sort of thing early and it will become second nature.
Without any additional changes (it can be made even simpler) that becomes
1
2
cout <<"-"<<  (num / gcd) / (den / gcd) << " " 
<< (num / gcd) % (den / gcd) << "/" << abs(den) / gcd << endl;



You won't see the speed difference here: the computer is too fast. But for bigger problems, the difference can be staggering.
Last edited on
Everybody thanks for your help.
It is very appreciated.
However, as for now, I would like to keep my code as it is, since I am a beginner and have an hard time reading someone else's code.
All I ask if possible, is to fix from line 24 to 27 of my code, so I will be able to get an error message when dividing by zero, and the program will not crash.
I am satisfied with the rest of the code.
Thank you in advance.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void num_den(int num, int den)
{
    try
    {
        //
        // put your existing code here!
        //
    }
    catch (const runtime_error& error)
    {
       // your error handling code here
       cout << e.what() << "\n";
    }
}


http://www.cplusplus.com/doc/tutorial/exceptions/
http://www.cplusplus.com/doc/tutorial/exceptions/
Last edited on
I would go out of my way to throw your error when den is set to zero. try to trap that down to a single point of entry. Otherwise you gonna need checks all over the place if you expand this to a big full functional tool (and assignments like this tend to do that, this has all the hallmarks of 'to be continued').

in your code, that would be here
cout << "enter denominator" << endl;
cin >> y;

just don't allow it, if y == 0, loop back and complain.
later when its a class, wherever you set den, same idea. should only be 1 place.
Last edited on
Topic archived. No new replies allowed.