Help with pi using classes

I am having trouble getting pi to output to the user by adding together my fractions that I have created. Here is my code. All of the math is working correctly I doubled checked in calculator. I am having trouble adding the fractions I get from the formula.
[center]
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
#include <iostream>
#include "fraction.h"
#include <cmath>
using namespace std;

int main() {

   //use k as 1-3
for( int k=0; k<3; k++){
   //create new Fraction objects
  Fraction f(1,pow(16,k));
  Fraction f1(4, 8*k+1);
  Fraction f2(2, 8*k+4);
  Fraction f3(1, 8*k+5);
  Fraction f4(1, 8*k+6);
 
  int num;
  int denom;
  int num_1;
  int denom_1;
  
  Fraction ans(num, denom);
  Fraction pi(num_1, denom_1);
  Fraction pi_1(num, denom);
  //first order of operations
  ans=f1.subtract(f2);
  //second order of operations
  ans=ans.subtract(f3);
  //third order of operations
  ans=ans.subtract(f4);
  //multiply by outside fraction
  ans=ans.multiply(f);

  //output Pi as a fraction
  
  cout<<"Pi equals " << f.to_string() << "(" << f1.to_string() <<"-"<< f2.to_string()
      << "-" << f3.to_string() << "-" << f4.to_string() <<") = " << ans.to_string()
      <<endl;
    //Find the answer to pi
  if(k==0||k==1||k==2){
    
  pi=ans.add(ans);
   pi_1=pi.add(pi);
   cout<<"Pi equals "<<pi_1.decimal()<<" as a decimal."<<endl;
  }

 }
}

My fraction.cpp is 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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include "fraction.h"
#include <sstream>

Fraction::Fraction() {
  numerator = 0;
  denominator = 1;
}

Fraction::Fraction(long long _numerator, long long _denominator) {
  numerator = _numerator;
  denominator = _denominator;

  // Reduce the fraction (as required by the class contract)
  // using our private helper function.
 
  reduce();

  // Ensure the denominator is not negative.
  // (Students will add code here for Assignment 7.)

}
void Fraction::reduce() {
  // Compute the GCD using a well-known algorithm.

  long long gcd = numerator;
  long long remainder = denominator;

  while(remainder != 0) {
    long long temp = remainder;
    remainder = gcd % remainder;
    gcd = temp;
  }

  // Divide both the numerator and denominator by the GCD.

  numerator /= gcd;
  denominator /= gcd;
}
string Fraction::to_string() {
  stringstream buffer;
  buffer << numerator << "/" << denominator;

  return buffer.str();
}
double Fraction::to_double(){
  double d;
  d=numerator/denominator;
  
  return d;
}
Fraction Fraction::add(Fraction other) {
  // Compute the sum.
  
  long long sum_numerator;
  long long sum_denominator;
  
  sum_numerator = numerator * other.denominator + other.numerator * denominator;
  
  sum_denominator = denominator * other.denominator;

  // Create the resulting fraction.
  
  Fraction result(sum_numerator, sum_denominator);

  // Return it.
  
  return result;
}

Fraction Fraction::multiply(Fraction other) {
  // Compute the product.
  
  long long product_numerator;
  long long product_denominator;
  
  product_numerator   = numerator * other.numerator;
  product_denominator = denominator * other.denominator;

  // Create the resulting fraction.
  
  Fraction result(product_numerator, product_denominator);

  // Return it.
  
  return result;
}
Fraction Fraction::divide(Fraction other){
    // Compute the quotient.
  
  long long sum_numerator;
  long long sum_denominator;
  
  sum_numerator = numerator * other.denominator;
  
  sum_denominator = denominator * other.numerator;

  // Create the resulting fraction.
  
  Fraction result(sum_numerator, sum_denominator);

  // Return it.
  
  return result;
}
Fraction Fraction::subtract(Fraction other){
    // Compute the diffrence.
  
  long long sum_numerator;
  long long sum_denominator;
  
  sum_numerator = numerator * other.denominator - other.numerator * denominator;
  
  sum_denominator = denominator * other.denominator;
  // Create the resulting fraction.
  
  Fraction result(sum_numerator, sum_denominator);

  // Return it.
  
  return result;
}

float Fraction::decimal(){
  return (float)numerator / (float)denominator;
}

my header file is:
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
73
#include <string>
using namespace std;

class Fraction {

private:
   long long numerator;
   long long denominator;
   /* This function reduces this fraction object.  It first
   * computes the greatest common divisor (GCD) of the numerator
   * and denominator.  Then, it divides both the numerator
   * and denominator by that GCD.
   */
  void reduce();
    
public:
  /* Fraction constructor
     to_double
    Turns a fraction into a double.
   */
 double  to_double();
 
  /* Fraction print
     will print the fraction out
  */
   void  print_fraction();
 
 /* Fraction default constructor
   *
   * Sets the fraction to 0/1 (which is 0).
   */
  Fraction(); 

  /* Fraction constructor
   *
   * Sets the fraction using the supplied values.
   * A denominator of 0 is not allowed -- although this is not checked.
   * (We need to learn about exceptions first.)
   *
   * Parameters:
   *   long long _numerator -- some numerator
   *   long long _denominator -- some denominator
   */
  Fraction(long long _numberator, long long _denominator);

    /* Fraction Constructor

     Will convert Fraction to string for printing. 

  */
  string to_string();

  /* Fraction Constructor 
     Will add two fractions together 
  */
  Fraction add(Fraction);
  
    /* Fraction Constructor 
     Will add multiply fractions 
  */
  Fraction multiply(Fraction);
  
    /* Fraction Constructor 
     Will subtract two fractions 
  */
  Fraction subtract(Fraction);

    /* Fraction Constructor 
     Will divide two fractions  
  */
  Fraction divide(Fraction);
    float decimal();
};
Last edited on
I don't know which algorithm for PI is intended to be used here. Could you give the name or details of the algorithm please.

However, keeping the fraction class out of the picture here (in case there are problems within it), I just tried the main program using type double throughout. I noticed that there are some uninitialised values, though they don't seem to play any particular role here, as those variables are over-written by other values later.

Unless I made some mistake, this is how it goes:
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
#include <iostream>
#include <iomanip>
#include <cmath>

using namespace std;

int main() 
{
    // use k as 1-3
    for ( int k=0; k<3; k++)
    {
        //  create new Fraction objects
        double f  = 1.0 / pow(16,k);
        double f1 = 4.0 / (8*k + 1);
        double f2 = 2.0 / (8*k + 4);
        double f3 = 1.0 / (8*k + 5);
        double f4 = 1.0 / (8*k + 6);

        int num;                    // not intiialised
        int denom;                  // not intiialised
        int num_1;                  // not intiialised
        int denom_1;                // not intiialised

        double ans  = (double) num / denom;     // not intiialised
        double pi   = (double) num_1 / denom_1; // not intiialised
        double pi_1 = (double) num / denom;     // not intiialised
        
        //  first order of operations
        ans = f1 - f2;
        
        //  second order of operations
        ans = ans - f3;
    
        //  third order of operations
        ans = ans - f4;
        
        //  multiply by outside fraction
        ans = ans * f;

        //  output Pi as a fraction
        cout << "Pi equals " << f 
             << "( " << f1 << " - " << f2 << " - " << f3 << " - " << f4 << " ) = " 
             << ans << endl;
        
        // Find the answer to pi
        if (k==0 || k==1 || k==2)
        {
            pi   = ans + ans;
            pi_1 = pi + pi;
            cout << "Pi equals " << pi_1  << " as a decimal." << endl;
        }

    }

}


and this is the output
Pi equals 1( 4 - 0.5 - 0.2 - 0.166667 ) = 3.13333
Pi equals 12.5333 as a decimal.
Pi equals 0.0625( 0.444444 - 0.166667 - 0.0769231 - 0.0714286 ) = 0.00808913
Pi equals 0.0323565 as a decimal.
Pi equals 0.00390625( 0.235294 - 0.1 - 0.047619 - 0.0454545 ) = 0.000164924
Pi equals 0.000659696 as a decimal.


Last edited on
http://mathworld.wolfram.com/BBPFormula.html

It's how pi is calculated to a spectacular number of places ... in hexadecimal! The really classy thing is that you can calculate any particular hexadecimal digit of pi without having to compute all the previous ones.
Last edited on
@lastchance Thank you.

Just to get a feel for how that might work, I tried this - though of course it is limited by the floating-point type I used.
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
#include <iostream>
#include <cmath>
#include <iomanip>

using namespace std;

typedef long double numeric;

numeric calc_digit(unsigned int k)
{
    unsigned int k8 = 8 * k;
    
    numeric a = 4.0 / (k8 + 1);
    numeric b = 2.0 / (k8 + 4);
    numeric c = 1.0 / (k8 + 5);
    numeric d = 1.0 / (k8 + 6);
    
    numeric sum = a - b - c - d;
        
    for (unsigned i=0; i<k; ++i)
    {
        sum /= 16;
    }
    
    return sum;
}

int main()
{   
    cout << fixed << setprecision(20);
        
    numeric total = 0.0;
    
    const int terms = 15;
    
    for (int k=0; k<terms; ++k)
    {
        numeric digit = calc_digit(k);
        total += digit;
        
        cout << setw(30) << digit 
             << setw(30) << total << '\n';
    }
        
    cout << "\n\ntotal = " << total << '\n';
}
        3.13333333333333333322        3.13333333333333333322
        0.00808913308913308913        3.14142246642246642245
        0.00016492392411510059        3.14158739034658152306
        0.00000506722085385878        3.14159245756743538179
        0.00000018789290093772        3.14159264546033631946
        0.00000000776775121518        3.14159265322808753471
        0.00000000034479329305        3.14159265357288082780
        0.00000000001609187716        3.14159265358897270498
        0.00000000000077957030        3.14159265358975227519
        0.00000000000003887115        3.14159265358979114644
        0.00000000000000198323        3.14159265358979312966
        0.00000000000000010310        3.14159265358979323266
        0.00000000000000000544        3.14159265358979323808
        0.00000000000000000029        3.14159265358979323830
        0.00000000000000000002        3.14159265358979323830


total = 3.14159265358979323830



@CHancock I read (fairly quickly) through the code for your Fraction class. Most of it looks reasonable, apart from the to_double() function which does integer division, and though it returns a type double, the value it contains will always be an integer.

The comments are misleading. almost all the member functions are labelled as "constructor". There are just two constructors:
1
2
3
    Fraction();

    Fraction(long long _numberator, long long _denominator);

I did a quick stand-alone test of the class and noticed in one case it have a positive numerator and negative denominator. Not sure whether that matters, though I'd tend to have the denominator always positive. My test wasn't thorough, there may be other issues.

Also, it is not a good idea to put "using namespace std;" inside a header file. I would remove it and instead put std:: in the one place where it is needed (std::string).
My problem is how to find the sum of the 3 different answers I receive from the iterations from the for loop. I am getting all the right answers but when I am using a class I don't know how to subtract the answers from the second and third iterations from the first iteration. So to summarize I have to take the answer from k=0, and subtract the answers form k=1 and k=0.
Last edited on
So to summarize I have to take the answer from k=0, and subtract the answers form k=1 and k=0.


Almost. According to the formula as I understand it, you just need to add all of them together.


Simplified version of original main()
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
#include <iostream>
#include "fraction.h"
#include <cmath>
using namespace std;

int main()
{
    Fraction total;

    // use k as 1-3
    for ( int k=0; k<3; k++)
    {
        // create new Fraction objects
        Fraction f(1, pow(16,k));
        Fraction f1(4, 8*k+1);
        Fraction f2(2, 8*k+4);
        Fraction f3(1, 8*k+5);
        Fraction f4(1, 8*k+6);
        
        // first order of operations
        Fraction ans = f1.subtract(f2);
        
        // second order of operations
        ans = ans.subtract(f3);
        
        // third order of operations
        ans = ans.subtract(f4);
        
        // multiply by outside fraction
        ans = ans.multiply(f);

        // output Pi as a fraction
        
        total = total.add(ans);
        
        cout << "Total = " << total.to_string() << "    " << total.decimal() << '\n';

    }
}
Last edited on
Thank you. I got it working I am suppose to see if the denominator is negative and if it is change the numerator to negative. Any idea how I would do that?
This is what I have so far.
1
2
3
4
5
 // Ensure the denominator is not negative.
  if(_denominator<0){
    _numerator=__numerator*-1;
    _denomintator=_denominator*-1;
}
Last edited on
Yes, what you have there looks reasonable, though you don't need the multiplication.

1
2
3
4
    if (  denominator < 0) {
        numerator   = -numerator;
        denominator = -denominator;
    }

with or without underscore depending on the context (which variables are involved).

You might need to check this after doing calculations, as well as when first constructing a new Fraction.
Sweet I have the program working how I want it to. Thank you so much for your help.
Topic archived. No new replies allowed.