Fraction class for finding square root 2 convegerence - c++

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.

Related

Don't know what Im doing wrong-adding,subtracting,dividing,multiplying rationals in c++

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;
}

Unexpected addition operator with my class

I apologize if the question is Naive.
I am trying to overload the addition operator for fractions. My intent was to add fractions but for some reason it is adding the integers. Can some one explain why is it performing the integer addition. Code is below.
#include <iostream>
#include <string>
using namespace std;
class Fraction{
long numerator;
long denominator;
long gcd(long num1, long num2);
long lcm(long num1, long num2);
public:
void convert_int_to_fraction(int num);
void reduce();
Fraction(int num);
Fraction(){
numerator = 0;
denominator = 0;
}
Fraction(long num, long den);
Fraction operator+(Fraction fraction);
friend ostream& operator<<(ostream& os, const Fraction& fracNumber);
};
void Fraction::convert_int_to_fraction(int num){
denominator = 1;
numerator = long(num);
reduce();
}
Fraction::Fraction(int num){
convert_int_to_fraction(num);
}
long Fraction::gcd(long num1, long num2){
if(num1 == 0)
return num2;
else
return (gcd(num2 % num1, num1));
}
//Math function to calculate LCM
long Fraction::lcm(long num1, long num2){
long great_Divisor = gcd(num1, num2);
return ((num1/great_Divisor) * num2);
}
//Reduce fraction to its minimal
void Fraction::reduce(){
if(denominator!=0){
long great_Divisor = gcd(numerator, denominator);
numerator /= great_Divisor;
denominator /= great_Divisor;
if(denominator < 0 && numerator > 0){
denominator = -denominator;
numerator = -numerator;
}
}
}
Fraction::Fraction(long num, long den):numerator(num), denominator(den){
reduce();
}
ostream& operator<<(ostream& os, const Fraction& fracNumber){
os << fracNumber.numerator << "/" << fracNumber.denominator ;
return os;
}
Fraction Fraction::operator+(Fraction fraction){
Fraction result;
long least_Multiple = lcm(denominator, fraction.denominator);
result.denominator = (least_Multiple);
long result_Numerator = ((numerator * (least_Multiple/denominator)) +
(fraction.numerator * (least_Multiple/fraction.denominator)));
result.numerator = (result_Numerator);
result.reduce();
return result;
}
int main(){
Fraction frac1(2,4);
cout << frac1 + 2 << endl;
return 0;
}
The output is 5/2 So I tried to do it the other way round
cout << 2 + frac1 << endl;
This is giving me error. So now I tried to fix this by implementing these two functions.
Fraction::operator int(){
return convert_fraction_to_int();
}
int Fraction::convert_fraction_to_int(){
return ((int)(numerator/denominator));
}
Now even the first operation cout doesnt work. But the best thing is everything works fine when I typecast the variables. Can anyone explain why it is working in the first case, why not in the second case and why broken in the third case.
.My intent was to add fractions but for some reason it is adding the integers. Can some one explain why is it performing the integer addition.
There is a converting constructor from int to Fraction.
frac1 + 2 is being converted to frac1 + Fraction(2) by the compiler.
Update
If you want the compiler to be able support both frac1 + 2 and 2 + frac1, you can make the operator+ function a non-member function.
friend Fraction operator+(Fraction const& lhs, Fraction const& rhs);
and implement it as:
Fraction operator+(Fraction const& lhs, Fraction const& rhs)
{
Fraction result;
// Needed to make lcm and gcd static member functions since
// they work independent of the member variables.
long least_Multiple = Fraction::lcm(lhs.denominator, rhs.denominator);
result.denominator = (least_Multiple);
long result_Numerator = ((lhs.numerator * (least_Multiple/lhs.denominator)) +
(rhs.numerator * (least_Multiple/rhs.denominator)));
result.numerator = (result_Numerator);
result.reduce();
return result;
}
Now, you can use
Fraction frac1(2,4);
Fraction frac2(3,7);
cout << frac1 + 2 << endl;
cout << 3 + frac1 << endl;
cout << frac1 + frac2 << endl;

multiplicative inverse of rational numbers c++

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;
}

The most accurate way to calculate numerator and denominator of a double

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.

+= Overloading in C++ problem

I am trying to overload the += operator for my rational number class, but I don't believe that it's working because I always end up with the same result:
RationalNumber RationalNumber::operator+=(const RationalNumber &rhs){
int den = denominator * rhs.denominator;
int a = numerator * rhs.denominator;
int b = rhs.numerator * denominator;
int num = a+b;
RationalNumber ratNum(num, den);
return ratNum;
}
Inside main
//create two rational numbers
RationalNumber a(1, 3);
a.print();
RationalNumber b(6, 7);
b.print();
//test += operator
a+=(b);
a.print();
After calling a+=(b), a is still 1/3, it should be 25/21. Any ideas what I am doing wrong?
operator+= is supposed to modify the object itself and return a reference. You are instead creating a new object and returning that. Something like this might work (untested code):
RationalNumber &RationalNumber::operator+=(const RationalNumber &rhs){
int den = denominator * rhs.denominator;
int a = numerator * rhs.denominator;
int b = rhs.numerator * denominator;
int num = a+b;
numerator = num;
denominator = den;
return *this;
}
Likewise operator+ should return a new object and can almost always be implemented in terms of operator+=:
RationalNumber RationalNumber::operator+(const RationalNumber &rhs){
RationalNumber tmp(*this);
tmp += rhs;
return tmp;
}
Finally, (now i'm getting off topic) it is usually considered best practice to use free functions instead of members where you can for things like binary operators.
You are not changing the object the operator is applied to.
x += 3;
should change x.