Assignment 1: Fractions Consider the following code, which implements a very simple 4-function calculator:

float n1, n2; char op;

while (cin >> n1 >> op >> n2) { switch (op) { case ‘+’: cout << n1 + n2 << endl; break; case ‘-‘: cout << n1 – n2 << endl; break; case ‘*’: cout << n1 * n2 << endl; break; case ‘/’: cout << n1 / n2 << endl; break;

} }

The code will read input consisting of simple arithmetic expressions, and for each it will display the result.

For example, it could compute

2.1 + 3.7 // answer: 5.8

1.732906E-9 / 4.5870021E-25 // answer: 3.77786e+15

By simply changing the type of the numbers n1 and n2 from float to some other type, the calculator can compute the answers for various kinds of number. For example, changing the type to int will mean that numbers are computed and displayed according to the rules of integer arithmetic, so you could compute that 7/2 is 3.

Your task is to define a class to represent and manipulate rational numbers (fractions), so that by simply changing the type of n1 and n2 to Rational the program will compute fractional arithmetic expressions such as these:

1/2 + 1/3 // answer: 5/6

1/3 – 1/4 // answer: 1/12

2/3 * 4/5 // answer: 8/15

3/7 / 2/3 // answer: 9/14

Find the calculator code and a skeleton version of the Rational class below. The class defines (but doesn’t fully implement) appropriate constructors to initialise instances of Rational, extract and insert operators for input and output of Rational values, and of course arithmetic operators to compute the results

# Background

A rational number is one that can be represented as the ratio of two integers, referred to as the numerator (n) and the denominator (d) and generally written n/d. Rational number arithmetic operations are defined as follows:

# Function points

1. Arithmetic operators: Define the 4 arithmetic operators so that they compute results according to the rules of rational arithmetic. At this level, you can assume that no numbers will have a zero denominator, and that division by zero does not occur.
2. Positive denominator: Modify your code so that rational numbers are always represented with a positive denominator. A rational number with a negative denominator can be converted to an equivalent number with a positive denominator by multiplying both numerator and denominator by -1.
3. Lowest terms: Modify your code so that rational numbers are always represented in lowest terms, which means that the numerator and denominator have no common factors. A rational number can be converted to an equivalent number in lowest terms by dividing both numerator and denominator by their greatest common divisor (gcd). An efficient algorithm for finding the greatest common divisor for two positive integers was described by Greek mathematician Euclid in 300 BC; look it up on the web and implement it as a helper function.
4. Mixed number output: Modify the insertion operator so that if the numerator is greater than or equal to the denominator, the value is displayed as a mixed number, using the format w,n/d, where w is the whole number part and n is less than d. For example, 9/4 should be displayed as 2,1/4.
5. Special-case output: Make sure your insertion operator works correctly for negative numbers, and where the fractional part of a mixed number is zero. For example, -4/3 should be displayed as -1,1/3, and 10/1 should be displayed as 10. As a special case, the rational number 0/1 should be displayed as 0.
6. Mixed number input: Extend the extraction operator so that in addition to accepting input as a common fraction, it also accepts whole numbers and mixed numbers. Thus the input 5 should generate the number 5/1, the input 3,2/3 should generate the number 11/3, and the input -1,1/2 should generate the number -3/2.
7. Percentage input: Extend the input extraction operator so that it will also accept inputs expressed as a percentage. Thus the input 23% should generate the rational number 23/100, and the input 50% should generate 1/2.
8. Decimal input: Extend the input extraction operator so that it will also accept inputs expressed as decimal fractions. Thus the input 0.3 should generate the value 3/10, -1.05 should generate -21/20, and 9.999 should generate 9999/1000.
9. Avoid needless overflow: The computation involved in performing arithmetic operations on rational numbers involves products of numerators and denominators. Even if the result could be reduced so that it falls within the allowable range of the representation, intermediate results may cause arithmetic overflow for rational numbers with large numerators or denominators unless it is handled carefully. For example, 999999/1000000 * 500000/999999 should give 1/2, but a naive implementation that involves the simple product of numerators and denominators will overflow the int type. Modify your code to produce correct results whenever the reduced number can be correctly represented without overflow. You will need to think carefully about the order in which expressions are evaluated and take full advantage of potential common factors to reduce the size of intermediate results. Note that simply using long to do the intermediate calculations is not an acceptable solution because long is not guaranteed to be able to represent larger values than int.
10. Error handling: Make sure that the program behaves sensibly in the event of errors. In particular, it should accommodate the following errors, reporting the appropriate message to cerr and exiting with the specified status.
 Condition Status Example input Corresponding error message zero denominator 1 2/3 / 0 Fractions: Zero denominator input format error 2 \$5 + \$2 Fractions: Input format error before ‘\$’

The correct way to deal with run-time errors is by raising runtime_error exceptions. The correct way to deal with input format errors is for the extraction operator to leave the input stream in a fail state and positioned immediately before the character that does not match the input specification. Then the errorhandling code can be written as follows:

# Assessment

While every new function point is an extension of the previous, you have to turn in the code for each of the assignment function points separately.