My program works fine except when a fraction has a numerator of 0 in the numerator when it does the inverse I get an arithmetic error and it crashes.
I've tried to check for zero int he numerator several different ways but I can't get the program to compile. Can someone give me some pointers.
Here's my code so far:
#include <lab58.h>
using namespace std;
int lcm(int u, int v)
{
if(u == 0 || v == 0)
return 0;
else
return (u * v) / gcd(u, v);
}
Rational rationalAdd(const Rational& augend, const Rational& addend)
{
Rational sum;
int lcm = ::lcm(augend.denominator, addend.denominator);
sum.numerator = lcm * augend.denominator / augend.numerator +
lcm * addend.denominator / addend.numerator;
sum.denominator = lcm;
rationalNormalize(sum);
return sum;
}
Rational rationalAdditiveInverse(const Rational *rational)
{
Rational additiveInverse;
additiveInverse.numerator = rational->numerator * -1;
additiveInverse.denominator = rational->denominator;
return additiveInverse;
}
Rational rationalSubtract(const Rational& minuend, const Rational& subtrahend)
{
return rationalAdd(minuend, rationalAdditiveInverse(&subtrahend));
}
// Function rationalMultiply returns multiplier x multiplicand. The
// result is returned in reduced form.
Rational rationalMultiply(const Rational& multiplier, const Rational& multiplicand)
{
Rational product;
product.numerator = multiplier.numerator * multiplicand.numerator;
product.denominator = multiplier.denominator * multiplicand.denominator;
rationalNormalize(product);
return product;
}
// Function rationalMultiplicativeInverse returns the multiplicative inverse.
// The multiplicative inverse, or reciprocal, of a number a is the
// number that, when multiplied by a, yields the multiplicative
// identity, 1. The multiplicative inverse of the fraction a/b is b/a.
Rational rationalMultiplicativeInverse(const Rational *rational)
{
Rational multiplicativeInverse;
multiplicativeInverse.numerator = rational->denominator;
multiplicativeInverse.denominator = rational->numerator;
return multiplicativeInverse;
}
// Function rationalDivide returns dividend / divisor. The result is
// returned in reduced form.
Rational rationalDivide(const Rational& dividend, const Rational& divisor)
{
return rationalMultiply(dividend, rationalMultiplicativeInverse(&divisor));
}
Here's the lab58.h file:
#ifndef LAB58_H
#define LAB58_H
#include <lab57.h>
using namespace std;
// Function lcm returns the least common multiple of u & v
int lcm(int u, int v);
// Function rationalAdd returns augend + addend. The result is
// returned in reduced form.
Rational rationalAdd(const Rational& augend, const Rational& addend);
// Function rationalAdditiveInverse returns the additive inverse.
// The additive inverse, or opposite, of a number a is the number
// that, when added to a, yields zero. Thus, the fraction a/b is
// returned as -a/b.
Rational rationalAdditiveInverse(const Rational *rational);
// Function rationalSubtract returns minuend - subtrahend. The result
// is returned in reduced form.
Rational rationalSubtract(const Rational& minuend, const Rational& subtrahend);
// Function rationalMultiply returns multiplier x multiplicand. The
// result is returned in reduced form.
Rational rationalMultiply(const Rational& multiplier, const Rational& multiplicand);
// Function rationalMultiplicativeInverse returns the multiplicative inverse.
// The multiplicative inverse, or reciprocal, of a number a is the
// number that, when multiplied by a, yields the multiplicative
// identity, 1. The multiplicative inverse of the fraction a/b is b/a.
Rational rationalMultiplicativeInverse(const Rational *rational);
// Function rationalDivide returns dividend / divisor. The result is
// returned in reduced form.
Rational rationalDivide(const Rational& dividend, const Rational& divisor);
#endif
Lab57.h:
/*
* Prototypes for operations on rational numbers.
*/
#ifndef LAB57_H
#define LAB57_H
#include <iostream>
using namespace std;
typedef struct
{
int numerator;
int denominator;
} Rational;
// Function rationalValid returns true if rational represents a valid
// rational number and false otherwise.
bool rationalValid(const Rational& rational);
// Function rationalNormalize reduces rational to lowest
// terms. Negative rationals should be manipulated so that the
// minus sign goes with the numerator. Zero is represented by zero
// (0) as the numerator and one (1) as the denominator.
void rationalNormalize(Rational& rational);
// Function rationalInput initializes rational from input stream in
istream& rationalInput(istream& in, Rational& rational);
// Function rationalOutput writes rational to output stream out in the
// format rational.numerator/rational.denominator
ostream& rationalOutput(ostream& out, const Rational& rational);
// Function gcd returns the greatest common divisor of u & v
int gcd(int u, int v);
#endif
Lab57main.C:
#include <iostream>
#include <lab57.h>
using namespace std;
int main()
{
Rational rational;
while (rationalInput(cin, rational))
{
if (rationalValid(rational))
{
rationalOutput(cout, rational);
cout << " = ";
rationalNormalize(rational);
rationalOutput(cout, rational);
cout << endl;
}
else
{
rationalOutput(cout, rational);
cout << " is invalid " << endl;
}
}
return EXIT_SUCCESS;
}
Related
This is the code that I wrote so far. Not sure what I am doing wrong. Every time I try to run it it displays "Invalid operands to binary expression" next to the "cin >> rational_2;" in the main file. If there is any that could help me I could deeply appreciate it. Also, provided the description what I need to do at the bottom.
Rational Arithmetic I
A rational number is a quotient of two integers. For example, 12/5, 12/–4, –3/4, and 4/6 are all rational numbers. A rational number is said to be in reduced form if its denominator is positive and its numerator and denominator have no common divisor other than 1. For example, the reduced forms of the rational numbers given above are 12/5, –3/1, –3/4, and 2/3.
Write a class called Rational with a constructor Rational(int, int) that takes two integers, a numerator and a denominator, and stores those two values in reduced form in corresponding private members. Ensure that the denominator is not 0. The class should have a private member function void reduce() that is used to accomplish the transformation to reduced form. The class should have an overloaded insertion operator << that will be used for output of objects of the class.
Rational Arithmetic II
Modify the class Rational of Programming Challenge 8 to add overloaded operators +, −, *, and / to be used for addition, subtraction, multiplication, and division.
#include <iostream>
using namespace std;
class Rational
{
private:
int denom;
int numer;
void reduce();
public:
Rational();
Rational(int num, int den);
//********** overloading mathematical operators ************
Rational operator-(const Rational& rightFr);
Rational operator*(const Rational& rightFr);
Rational operator/(const Rational& rightFr);
Rational operator+(const Rational& rightFr);
//********** overloading relational operators ************
bool operator == (const Rational& rightFr);
// F R I E N D F U N C T I I O N S
friend ostream& operator<<(ostream& the_output, Rational&);
};
//Rational.cpp file
#include "Rational.h"
Rational::Rational()
{
}
Rational::Rational(int num, int den)
{
numer = num;
denom = den;
reduce();
}
// reduce method
void Rational::reduce()
{
int topnum;
if (numer > denom )
{
topnum = numer;
}
else
{
topnum = denom;
}
int divisor = 2;
while (divisor <= topnum)
{
if (numer%divisor == 0 && denom%divisor == 0)
{
numer /= divisor;
denom /= divisor;
divisor =2;
}
else
{
divisor++;
}
}
if(denom < 0 )
{
denom *= -1;
numer *= -1;
}
}
// Operator Overload for Adding
Rational Rational:: operator+(const Rational &rightFr){
Rational ret_val( 1, 1);
ret_val.numer = this ->numer * rightFr.denom + this->denom * rightFr.numer;
ret_val.denom = this-> denom + rightFr.denom;
return ret_val;
}
// Operator Overload for Sub
Rational Rational:: operator-(const Rational &rightFr){
Rational ret_val( 1, 1);
ret_val.numer = this ->numer * rightFr.denom - this->denom * rightFr.numer;
ret_val.denom = this-> denom - rightFr.denom;
return ret_val;
}
// Operator Overload for Mult.
Rational Rational::operator * (const Rational &rightFr){
Rational ret_val(1,1);
ret_val.numer = this ->numer * rightFr.numer;
ret_val.denom = this ->numer * rightFr.numer;
reduce();
return ret_val;
}
Rational Rational::operator / (const Rational &rightFr){
Rational ret_val(1,1);
ret_val.numer = this ->numer * rightFr.numer;
ret_val.denom = this ->denom * rightFr.denom;
reduce();
return ret_val;
}
bool Rational::operator==(const Rational &rightFr)
{
bool answer = false;
if( numer == rightFr.numer && this-> denom == rightFr.denom)
{
answer = true;
}
return answer;
}
// friend functions
ostream& operator<<(ostream& the_output, Rational& obj ){
the_output << obj.numer <<"/"<< obj.denom << endl;
return the_output;
}
//main file
#include <iostream>
#include <iomanip>
#include "Rational.h"
using namespace std;
int main()
{
Rational rational_1(5, 6);
Rational rational_2;
Rational rational_Add, rational_Sub, rational_Mult, rational_Divide;
cout << "Enter numerator and denominator separated by a space :";
cin >> rational_2; // this is were I get the error
rational_Add = rational_1 + rational_2;
rational_Sub = rational_1 - rational_2;
rational_Mult = rational_1 * rational_2;
rational_Divide = rational_1 / rational_2;
cout << "rational_1 : " << rational_1 << endl
<< "rational_2 : " << rational_2 << endl
<< "rational_Add : " << rational_Add << endl
<< "rational_Sub : " << rational_Sub << endl
<< "rational_Mult : " << rational_Mult << endl
<< "rational_Divide : " << rational_Divide << endl;
return 0;
}
cin >> rational_2; // this is were I get the error
Please implement istream operator overloading operator>>. For example,
friend istream& operator>>(istream& is, Rational& obj) {
is >> obj.numer >> obj.denom;
return is;
}
I'm writing code that uses friend functions but I am not sure why I get the error "is a private member of" in the function "sum" since I declared the function as a friend in the header file.
Header File:
#include <iostream>
class rational
{
public:
// ToDo: Constructor that takes int numerator and int denominator
rational (int numerator = 0, int denominator = 1);
// ToDo: Member function to write a rational as n/d
void set (int set_numerator, int set_denominator);
// ToDo: declare an accessor function to get the numerator
int getNumerator () const;
// ToDo: declare an accessor function to get the denominator
int getDenominator () const;
// ToDo: declare a function called Sum that takes two rational objects
// sets the current object to the sum of the given objects using the
// formula: a/b + c/d = ( a*d + b*c)/(b*d)
friend rational sum (const rational& r1, const rational& r2);
void output (std::ostream& out);
// member function to display the object
void input (std::istream& in);
private:
int numerator;
int denominator;
};
Source File:
#include <iostream>
using namespace std;
// takes two rational objects and uses the formula a/b + c/d = ( a*d + b*c)/(b*d) to change the numerator and denominator
rational sum (rational r1, rational r2)
{
// formula: a/b + c/d = ( a*d + b*c)/(b*d)
cout << endl;
numerator = ((r2.denominator * r1.numerator) + (r1.denominator * r2.numerator));
denominator = (r1.denominator * r2.denominator);
}
rational sum (rational r1, rational r2) is a totally new function (no way to relate to the class rational) that accepts two rationals and returns a rational.
The correct way to implement the needed class method would be rational rational::sum (const rational& r1, const rational& r2)
Overall comment: Use capitalized first letter for classes (Rational)
You want something like this:
rational sum (const rational& r1, const rational& r2)
{
// formula: a/b + c/d = ( a*d + b*c)/(b*d)
int numerator = ((r2.denominator * r1.numerator) + (r1.denominator * r2.numerator));
int denominator = (r1.denominator * r2.denominator);
return rational(numerator, denominator);
}
I made a class that can add, multiply and divide fractions which is presented below
class fraction
{
unsigned long long num, denom;
public:
fraction(int n, int d): num{n}, denom{d} {};
fraction& operator+=(fraction frac);
fraction& operator*=(fraction frac);
fraction& operator/=(fraction frac);
friend ostream& operator<<(ostream& os, const fraction& frac);
};
fraction& fraction::operator+=(fraction frac)
{
unsigned long long least_mult = lcm(denom, frac.denom); // Least-Common Multiple
num *= least_mult/denom;
num += frac.num*least_mult/frac.denom,
denom = least_mult;
return *this;
}
fraction& fraction::operator*=(fraction frac)
{
num *= frac.num;
denom *= frac.denom;
return *this;
}
fraction& fraction::operator/=(fraction frac)
{
num *= frac.denom;
denom *= frac.num;
return *this;
}
ostream& operator<<(ostream& os, const fraction& frac)
{
os << frac.num << '/' << frac.denom;
return os;
}
fraction operator+(fraction a, fraction b) {return a+=b;}
fraction operator*(fraction a, fraction b) {return a*=b;}
fraction operator/(fraction a, fraction b) {return a/=b;
}
When I try to compute square root two convergence using sqrt_two = 1 + 1/(1+sqrt_two) recursive relation when I get up to 4478554083/3166815962, the next value is 8399386631/7645270045 which is totally off as it is about 1.098, and therefore all the subsequent values are wrong too.
int main()
{
fraction one(1, 1), sqrt_two(3,2);
for(int i = 1; i < 50; ++i)
{
sqrt_two = one + one/(one+sqrt_two);
cout << sqrt_two << endl;
}
return 0;
}
I have tried 1+1/(1+8399386631/7645270045)) manually on a calculator and the result is still a square root convergent.
Looking at your code, there are lines that are susceptible to overflow. Perhaps one has happened in this case. For example,
num += frac.num*least_mult/frac.denom,
(which looks like it contains a typo, incidentally).
So, I'd suggest you see how to check for overflow, and then somehow incorporate it into your class. I'm not sure what you should do in such a case, though.
To compute the step that gives bad results you multiply two numbers of about 32 bits. The result exceeds the long long size (64 bit if unsigned) and you end up having wrong result because of overflow. A calculator (using more bits or silently converting to floating point) overcomes this problem.
I have implemented class NaturalNum for representing a natural number of "infinite" size (up to 4GB).
I have also implemented class RationalNum for representing a rational number with infinite accuracy. It stores the numerator and the denominator of the rational number, both of which are NaturalNum instances, and relies on them when performing any arithmetic operation issued by the user.
The only place where precision is "dropped by a certain degree", is upon printing, since there's a limit (provided by the user) to the number of digits that appear after the decimal (or non-decimal) point.
My question concerns one of the constructors of class RationalNum. Namely, the constructor that takes a double value, and computes the corresponding numerator and denominator.
My code is given below, and I would like to know if anyone sees a more accurate way for computing them:
RationalNum::RationalNum(double value)
{
if (value == value+1)
throw "Infinite Value";
if (value != value)
throw "Undefined Value";
m_sign = false;
m_numerator = 0;
m_denominator = 1;
if (value < 0)
{
m_sign = true;
value = -value;
}
// Here is the actual computation
while (value > 0)
{
unsigned int floor = (unsigned int)value;
value -= floor;
m_numerator += floor;
value *= 2;
m_numerator *= 2;
m_denominator *= 2;
}
NaturalNum gcd = GCD(m_numerator,m_denominator);
m_numerator /= gcd;
m_denominator /= gcd;
}
Note: variables starting with 'm_' are member variables.
Thanks
The standard library contains a function for obtaining the significand and exponent, frexp.
Just multiply the significand to get all bits before decimal point and set appropriate denominator. Just don't forget the significand is normalized to be between 0.5 and 1 (I would consider between 1 and 2 more natural but whatever) and that it has 53 significant bits for IEEE double (there are no practically used platforms that would use different floating point format).
I'm not 100% confident in the math that you have for the actual computation only because I haven't really examined it, but I think the below method removes the need to use the GCD function which could bring in some unnecessary running time.
Here is the class I came up with. I haven't fully tested it, but I produced a couple billion random doubles and the asserts never fired, so I'm reasonably confident in its usability, but I would still test the edge cases around INT64_MAX a little more.
If I'm not mistaken, the running time complexity of this algorithm is linear with respect to the size in bits of the input.
#include <iostream>
#include <cmath>
#include <cassert>
#include <limits>
class Real;
namespace std {
inline bool isnan(const Real& r);
inline bool isinf(const Real& r);
}
class Real {
public:
Real(double val)
: _val(val)
{
if (std::isnan(val)) { return; }
if (std::isinf(val)) { return; }
double d;
if (modf(val, &d) == 0) {
// already a whole number
_num = val;
_den = 1.0;
return;
}
int exponent;
double significand = frexp(val, &exponent); // val = significand * 2^exponent
double numerator = val;
double denominator = 1;
// 0.5 <= significand < 1.0
// significand is a fraction, multiply it by two until it's a whole number
// subtract exponent appropriately to maintain val = significand * 2^exponent
do {
significand *= 2;
--exponent;
assert(std::ldexp(significand, exponent) == val);
} while (modf(significand, &d) != 0);
assert(exponent <= 0);
// significand is now a whole number
_num = significand;
_den = 1.0 / std::ldexp(1.0, exponent);
assert(_val == _num / _den);
}
friend std::ostream& operator<<(std::ostream &os, const Real& rhs);
friend bool std::isnan(const Real& r);
friend bool std::isinf(const Real& r);
private:
double _val = 0;
double _num = 0;
double _den = 0;
};
std::ostream& operator<<(std::ostream &os, const Real& rhs) {
if (std::isnan(rhs) || std::isinf(rhs)) {
return os << rhs._val;
}
if (rhs._den == 1.0) {
return os << rhs._num;
}
return os << rhs._num << " / " << rhs._den;
}
namespace std {
inline bool isnan(const Real& r) { return std::isnan(r._val); }
inline bool isinf(const Real& r) { return std::isinf(r._val); }
}
#include <iomanip>
int main () {
#define PRINT_REAL(num) \
std::cout << std::setprecision(100) << #num << " = " << num << " = " << Real(num) << std::endl
PRINT_REAL(1.5);
PRINT_REAL(123.875);
PRINT_REAL(0.125);
// double precision issues
PRINT_REAL(-10000000000000023.219238745);
PRINT_REAL(-100000000000000000000000000000000000000000.5);
return 0;
}
Upon looking at your code a little bit more, there's at least a problem with your testing for infinite values. Note the following program:
#include <numeric>
#include <cassert>
#include <cmath>
int main() {
{
double d = std::numeric_limits<double>::max(); // about 1.7976931348623e+308
assert(!std::isnan(d));
assert(!std::isinf(d));
// assert(d != d + 1); // fires
}
{
double d = std::ldexp(1.0, 500); // 2 ^ 700
assert(!std::isnan(d));
assert(!std::isinf(d));
// assert(d != d + 1); // fires
}
}
In addition to that, if your GCD function doesn't support doubles, then you'll be limiting yourself in terms of values you can import as doubles. Try any number > INT64_MAX and the GCD function may not work.
I have written the following class for modifying a Fraction object.
#include "Fraction.h"
#include "GCD.h"
#include <iostream>
using std::cout;
//Implementation of the timesEq() member function
//Performs similar operation as the *= operator on the built-in types
const Fraction & Fraction::timesEq(const Fraction & op )
{
numerator *= op.numerator;
denominator *= op.denominator;
simplify(); // will make sure that denominator is positive and
// will invoke gcd() function to reduce fraction
// as much as possible
return (*this); // returns the object which invoked the method
}
const Fraction & Fraction::plusEq (const Fraction & op )
{
numerator *= op.denominator;
numerator += op.numerator * denominator;
denominator *= op.denominator;
simplify(); // will make sure that denominator is positive and
// will invoke gcd() function to reduce fraction
// as much as possible
return (*this); // returns the object which invoked the method
}
const Fraction & Fraction::minusEq (const Fraction & op )
{
numerator *= op.denominator;
denominator = denominator * op.denominator;
numerator -= op.numerator;
simplify(); // will make sure that denominator is positive and
// will invoke gcd() function to reduce fraction
// as much as possible
return (*this); // returns the object which invoked the method
}
const Fraction & Fraction::divideEq (const Fraction & op )
{
numerator *= op.denominator;
denominator *= op.numerator;
simplify(); // will make sure that denominator is positive and
// will invoke gcd() function to reduce fraction
// as much as possible
return (*this); // returns the object which invoked the method
}
Fraction Fraction::negate(void) const
{
return (*this * -1);
}
void Fraction::display(void)const {
cout << numerator << "/" << denominator;
}
void Fraction::simplify(void)
{
gcd = gcd(numerator, denominator);
numerator /= gcd;
denominator /= gcd;
}
But am having trouble with the negate function.
I am using the function like so: B = A.negate(), and as such, I cannot modify the original A object, but need to assign the negated object to B.
Right now the implementation I have is giving an error:
Error: no operator "*" matches these operands
operand types are: const Fraction * int
I'm not sure what I am doing wrong. What needs to be changed?
Assuming you have a constructor that takes two ints as arguments (if you don't, you should, and not just for the sake of my answer), do this:
return Fraction(-numerator, denominator);