CS20006 Assignment 2 Solved

35.00 $

Category:

Description

Rate this product

C

We want to design a User-Defined Datatype (UDT) Fraction for rational numbers. It should behave like the built-in numerical types (for example, int). The concept, interface and implementation of the datatype are discussed below before the engineering requirements and tasks are specified.

1. Concept: Here we outline the basic concept for a Fraction datatype. class Fraction is to be designed as a UDT representing reduced (normalized) proper fractions (rational numbers) of the form pq where

p,q ∈ int, q > 0, and gcd(p,q) = 1. Hence, 12, 6, and 2 all will be represented only as 2. 1893 3

Most operations available in C++ for int type should be available in their respective syntax and semantics for Fraction. Some operations (like variants of assignments) have been skipped for simplicity and some operations (like logical negation) have been given new semantics.

2. Interface: The expected behavior of the datatype (operations) are discussed in this section.

• Constructors: All constructors must only create normalized fractions. They include

  • –  Constructor with a pair of int values for the numerator and denominator properly defaulted.
    • ∗  Invoked as a default constructor, it would create: pq ≡ 1
    • ∗  Invoked with one parameter m, it would create: pq ≡ m1
    • ∗  Invoked with two parameters m and n, it would create: pq ≡ mn . If n < 0, the construction willbedonewith−mand−n. Ifm=0,nistakentobe1. Naturally,ifn=0,theprogram would call exit(1)1.
  • –  Constructor from a single double value d. The class Fraction should use a preset int precision

to convert from d as:

p ≡ ⌊d ∗ precision⌋ q precision

This constructor should not allow implicit conversion.
– Copy Constructor: Should implement the usual semantics

  • Destructor: Should implement the usual semantics
  • Copy Assignment Operator: Should implement the usual semantics
  • Unary Arithmetic Operators: The operator should take a Fraction value and produce a Fraction value after the operation. It may or may not change the operand.

    – Unary minus operator: −􏰃p􏰄 ≡ −p qq

    – Unary plus operator: +􏰃p􏰄 ≡ +p qq

    – Prefix pre-decrement operator for dividendo returns p ← p − 1 = p−q qqq

    – Prefix pre-increment operator for componendo returns p ← p + 1 = p+q qqq

    – Postfix post-decrement operator for lazy dividendo returns p & performs p ← p − 1 = p−q qqqq

    – Postfix post-increment operator for lazy componendo returns p & performs p ← p + 1 = p+q qqqq

  • Binary Arithmetic Operators (using friend functions): The operator should take a pair of Fraction values and produce a Fraction value after the operation. The operands must not be modified. The operator returns the result of:

    – Addition: Adding the First operand to the Second operand
    – Subtraction: Subtracting the Second operand from the First operand
    – Multiplication: Multiplying the First operand with the Second operand

1Constructors should not throw an exception

1

  • –  Division: Dividing the First operand by the Second operand. Should throw an exception if the divider (Second operand) is zero
  • –  Remainder: Remainder2 of division of the First operand by the Second operand. Should throw an exception if the divider (Second operand) is zero
  • Binary Relational Operators: The operator should take a pair of Fraction values and produce a bool result. The operands must not be modified. The operator returns true when

    – Operands are Equal
    – Operands are Not Equal
    – First operand is Less than Second operand
    – First operand is Less than or Equal to Second operand – First operand is More than Second operand
    – First operand is More than or Equal to Second operand

  • Special Operators: The negation (!) operator should take a Fraction value and produce an inverted Fraction value as ! 􏰃 p 􏰄 ≡ q . The operand must not be modified and should throw an

    qp

    exception if the fraction is zero.

  • I/O Operators (using friend functions): Should implement the usual semantics for streaming.
    • –  Output: Streaming to ostream. pq to be output as p / q. The divider should be omitted if pq is a whole number.
    • –  Input: Streaming from istream. Read a pair of int p and q, form pq and normalize
  • Constants of the Datatype: Unity and Zero should be defined as static constants

    – sc fUnity = Fraction() ≡ 1

    – sc fZero = Fraction(0) ≡ 01

  • Utility Functions of the Datatype: The following static functions should be available:

    – precision() to return the constant to be used in conversion from double
    – int gcd(int, int) finds the greatest common divisor (gcd) for two positive integers – int lcm(int, int) finds the least common multiple (lcm) for two positive integers

    3. Implementation: A suggestive implementation for the datatype is given here. Any other choice of implementation consistent with the interfaces would be acceptable.

    • Data Members
    – Numerator of type int
    – Denominator of type unsigned int

    • Utility Function
    – A function to normalize a fraction to its proper form. Also, sets q to 1 if p is 0.

    4. Engineering: Finally, we engineer the concept based on the expectations of the interface and implemen- tation to create the Fraction datatype. The tasks therein include:

(a) Design the interface for class Fraction containing the exposed member functions (signatures only) as specified in Interface section. Explain the design considerations (like parameters, types, call/return-by-value/reference, const-ness, initialization, exception etc.) in comments before every member function to illustrate your design understanding and depth.

Put the design in “Fraction.hxx” Note: Marks will be distributed as:

2What is the meaning of remainder in rational algebra?

[20]

2

Constructors
Destructor
Copy Assignment Operator Unary Arithmetic Operators Binary Arithmetic Operators Binary Relational Operators Special Operators
I/O Operators
Constants of the Datatype Utility Functions of the Datatype

[0.5 + 1 + 0.5 = 2] [0.5] [0.5] [0.5 * 6 = 3] [1 * 5 = 5] [0.5 * 6 = 3] [0.5] [1 * 2 = 2] [1 * 2 = 2] [0.5 * 3 = 1.5]

  1. (b)  Add the implementation for class Fraction containing the concealed data members and member functions as specified in Implementation section. Explain the design considerations in comments before every member. [0]
  2. (c)  Implement all member functions of class Fraction and inline as appropriate. Add implementa- tion notes as comments for every function.

    Put the implementations of the inline member functions in “Fraction.hxx”. Put the non-inline member function implementations and static constants in “Fraction.cxx”

Note: Marks will be distributed as:

Constructors
Destructor
Copy Assignment Operator Unary Arithmetic Operators Binary Arithmetic Operators Binary Relational Operators Special Operators
I/O Operators
Constants of the Datatype Utility Functions of the Datatype

[30]

  1. (d)  Test your implementation using the void TestFraction() below from “TestFraction.cxx” file. Finally, int main() (file “Main.cxx”) invokes TestFraction() to perform the test.

    Put your test results in “Fraction.out” Note:

    • Ifyouareunabletowritetheinterface(signature)ofamemberfunction,skipitin”Fraction.hxx” and comment out its use in “TestFraction.cxx”
    • If you are unable to write the implementation of a member function, skip it in “Fraction.hxx” or “Fraction.cxx” and comment out its use in “TestFraction.cxx”
    • Obviously, the above exclusions will not work if you fail to do the basic methods like constructor, destructor, assignment etc. In that case, please contact the TA.
  2. (e)  Submit “Fraction.hxx”, “Fraction.cxx”, “TestFraction.cxx”, “Main.cxx”, and “Fraction.out” in a zip file assgn-2-<your roll>.zip.

    Note:

    • “Fraction.hxx” and “Fraction.cxx” will be evaluated
    • “Fraction.out” will be checked for completeness of operators
    • “TestFraction.cxx” and “Main.cxx” will be used if the TA needs to build and rerun the entire

      project

    • If a particular operator does not compile, its marks for interface design will be zero
    • If a particular operator does not give correct result by test, its marks for implementation will be

zero

3

[2 * 3 = 6] [1] [2] [0.5 * 4 + 1 * 2 = 4] [1 * 5 = 5] [0.5 * 6 = 3] [1 + 1 = 2] [1.5 * 2 = 3] [0.5 * 2 = 1] [3]

// File: TestFraction.cxx
// Contains: void TestFraction()
/************ C++ Headers ************************************/
#include <iostream>
using namespace std;
/************ PROJECT Headers ********************************/
#include "Fraction.hxx"
void TestFraction() {
    cout << "\nTest Fraction Data Type" << endl;
    // CONSTRUCTORS
    // ------------
    Fraction f1(5, 3);
    Fraction f2(7.2);
    Fraction f3;
    cout << "Fraction f1(5, 3) = " << f1 << endl;
    cout << "Fraction f2(7.2) = " << f2 << endl;
    cout << "Fraction f3 = " << f3 << endl;
    // BASIC ASSIGNEMENT OPERATOR
    // --------------------------
    cout << "Assignment (Before): f3 = " << f3 << ". f1 = " << f1 << endl;
    f3 = f1;
    cout << "Assignment (After): f3 = " << f3 << ". f1 = " << f1 << endl;
    f3 = Fraction::sc_fUnity;
    // UNARY ARITHMETIC OPERATORS
    // --------------------------
    f3 = -f1;
    cout << "Unary Minus: f3 = " << f3 << ". f1 = " << f1 << endl;
    // Pre-decrement. Dividendo
    f3 = Fraction::sc_fUnity;
    cout << "Pre-Decrement (Before): f3 = " << f3 << ". f1 = " << f1 << endl;
    f3 = --f1;
    cout << "Pre-Decrement (After): f3 = " << f3 << ". f1 = " << f1 << endl;
    // Post-decrement. Lazy Dividendo
    f3 = Fraction::sc_fUnity;
    cout << "Post-Decrement (Before): f3 = " << f3 << ". f1 = " << f1 << endl;
    f3 = f1--;
    cout << "Post-Decrement (After): f3 = " << f3 << ". f1 = " << f1 << endl;
    // Pre-increment. Componendo
    f3 = Fraction::sc_fUnity;
    cout << "Pre-Increment (Before): f3 = " << f3 << ". f1 = " << f1 << endl;
    f3 = ++f1;
    cout << "Pre-Increment (After): f3 = " << f3 << ". f1 = " << f1 << endl;
    // Post-increment. Lazy Componendo
    f3 = Fraction::sc_fUnity;
    cout << "Post-Increment (Before): f3 = " << f3 << ". f1 = " << f1 << endl;
    f3 = f1++;
    cout << "Post-Increment (After): f3 = " << f3 << ". f1 = " << f1 << endl;

4

// BINARY ARITHMETIC OPERATORS USING FRIEND FUNCTIONS
// --------------------------------------------------
f1 = Fraction(5, 12);
f2 = Fraction(7, 18);
f3 = f1 + f2;
cout << "Binary Plus: f3 = " << f3 << ". f1 = " << f1
     << ". f2 = " << f2 << endl;
f1 = Fraction(16, 3);
f2 = Fraction(22, 13);
f3 = f1 - f2;
cout << "Binary Minus: f3 = " << f3 << ". f1 = " << f1
     << ". f2 = " << f2 << endl;
f1 = Fraction(5, 12);
f2 = Fraction(18, 25);
f3 = f1 * f2;
cout << "Multiply: f3 = " << f3 << ". f1 = " << f1
     << ". f2 = " << f2 << endl;
f1 = Fraction(5, 12);
f2 = Fraction(7, 18);
f3 = f1 / f2;
cout << "Divide: f3 = " << f3 << ". f1 = " << f1
     << ". f2 = " << f2 << endl;
f1 = Fraction(5, 12);
f2 = Fraction(7, 18);
f3 = f1 % f2;
cout << "Residue: f3 = " << f3 << ". f1 = " << f1
     << ". f2 = " << f2 << endl;
// BINARY RELATIONAL OPERATORS
// ---------------------------
f1 = Fraction(5, 12);
f2 = Fraction(7, 18);
bool bTest = f1 == f2;
cout << "Equal: Test = " << ((bTest)? "true": "false")
     << ". f1 = " << f1 << ". f2 = " << f2 << endl;
bTest = f1 != f2;
cout << "Not Equal: Test = " << ((bTest)? "true": "false")
     << ". f1 = " << f1 << ". f2 = " << f2 << endl;
bTest = f1 < f2;
cout << "Less: Test = " << ((bTest)? "true": "false")
     << ". f1 = " << f1 << ". f2 = " << f2 << endl;
f1 = Fraction(5, 12);
f2 = Fraction(7, 18);
f3 = Fraction(5, 12);
bTest = f1 <= f2;
cout << "Less Equal: Test = " << ((bTest)? "true": "false")
     << ". f1 = " << f1 << ". f2 = " << f2 << endl;
bTest = f1 <= f3;
cout << "Less Equal: Test = " << ((bTest)? "true": "false")
     << ". f1 = " << f1 << ". f3 = " << f3 << endl;

5

    bTest = f1 > f2;
    cout << "Greater: Test = " << ((bTest)? "true": "false")
         << ". f1 = " << f1 << ". f2 = " << f2 << endl;
    bTest = f1 >= f2;
    cout << "Greater Equal: Test = " << ((bTest)? "true": "false")
         << ". f1 = " << f1 << ". f2 = " << f2 << endl;
    bTest = f1 >= f3;
    cout << "Greater Equal: Test = " << ((bTest)? "true": "false")
         << ". f1 = " << f1 << ". f3 = " << f3 << endl;

return; }

// End-of-File: TestFraction.cxx
// File: Main.cxx
// Contains: int main()
/************ C++ Headers ************************************/
#include <iostream>
using namespace std;
/************ PROJECT Headers ********************************/
#include "Fraction.hxx"
void TestFraction();
int main() {
    TestFraction();

return 0; }

// End-of-File: Main.cxx

6

  • Assignment-2-vbailq.zip