Very odd calculation issue

Hi all,

I've been troubleshooting this issue for about 2 hours now and just can't seem to figure out what on Earth is happening. I've narrowed it down to one particular function, but why this function is acting this way is completely beyond me as the same function works fine if I create a new file and copy & paste the necessary code in.

The findGCF function is supposed to take a numerator and denominator value and calculate the greatest common factor. Whether or not this function returns a value is not something I'm concerned about, as I mainly want the value of final.gcf to change. This function worked just fine when I first wrote the program without using classes, and worked fine again when rewriting with structs, compiling with either CodeBlocks or g++. For some reason though, it keeps returning the lowest value as the GCF... however, there's a catch. If I put ANY sort of cout statement in that function, it magically starts calculating correctly. The cout statement doesn't even have to reference an actual value - it can be a simple string, and as far as I can tell it doesn't matter where in the function it goes.

To add to the weirdness, I created a new cpp file, copied the necessary prototypes and such in and ran the program. No issues at all. I'm at a loss. The code looks exactly the same between the two files, but one is acting like it got hit in the head.

Anyway, here's the code for the original file. I've taken out some of the function definitions that are not needed to troubleshoot in order for this to fit:

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
126
127
128
#include <iostream>     // Standard iostream include directive
#include <string>       // Used for strings
#include <cstdlib>      // Used for atoi functions

using namespace std;    // Use the standard namespace

class Fraction         // Create a class for our fractions
{
    private:
        int denominator;
        int numerator;
        string input;
        int gcf;            // Define our greatest common factor variable
    public:
        //void setInput(string newFract) {input = newFract;};
        void setInput(int a, int b);  // Test function
        int getNumerator() {return numerator;};
        int getDenominator() {return denominator;};
        //bool parseFract();
        //void addFract(Fraction first, Fraction second);
        int findGCF();
        void simplify();
};

int main()
{
  Fraction first, second, final;
  string input, answer;               // Define answer and input
  bool check;                         // Define boolean variable as part of data input validation

  cout << "\n\n***This program will ask for two fractions.  It will then add them together and display the result,\n"
       << "then show the simplified result.***\n\n";

  do                                                                      // Part of a do-while allowing the user to enter a new set of values
    {
      /*do                                                                  // Run this at least once...
        {
            cout << "\n\nEnter the first fraction in the form of a/b: ";    // to ask for the first fraction.
            cin >> input;
            first.setInput(input);
            check = first.parseFract();    // and parse the entered string to pull out the values in integers...
            cout << "Fraction 1: " << first.getNumerator() << "/" << first.getDenominator() << endl;
        }while(!check);                                                     // while checking to ensure all values are valid and the denominator is not 0.

        do
          {
            cout << "Enter the second fraction in the form of a/b: ";       // Ask for the second fraction.
            cin >> input;
            second.setInput(input);
            check = second.parseFract();
            cout << "Fraction 2: " << second.getNumerator() << "/" << second.getDenominator() << endl;
          }while(!check);*/

        /*first.setInput(4,5);
        cout << "Fraction 1: " << first.getNumerator() << "/" << first.getDenominator() << endl;
        second.setInput(5,7);
        cout << "Fraction 2: " << second.getNumerator() << "/" << second.getDenominator() << endl;*/
        final.setInput(53,35);

        //final.addFract(first, second);                                     // Run function to add the fractions together.

        cout << "\n\nWhen added together your fractions become: " << final.getNumerator() << "/" << final.getDenominator() << endl << endl;

        cout << "gcf: " << final.findGCF() << endl;                                               // Run function to find the GCF.
        final.simplify();

        cout << "After being simplified: " << final.getNumerator() << "/" << final.getDenominator() << endl << endl;

        cout << "Would you like to try a new set of numbers?: ";            // Ask the user if they would like to use new fractions.
        cin >> answer;                                                      // Take their answer.

    }while(answer[0]=='y' || answer[0]=='Y');                               // Ensure that either a lowercase or uppercase Y will suffice, whether or not the user typed 'yes' or 'y'.

  return 0;
}

void Fraction::setInput(int a, int b)
{
    numerator = a;
    denominator = b;
}

int Fraction::findGCF()         // This function finds the GCF
{
  int a, b, c, m;        // Define necessary variables.


  a=numerator;          // Set a to the value of our final numerator to keep the code clean.
  b=denominator;        // Set b to the value of our final denominator to keep the code clean.

    if(a>=b)                    // If a is greater than or equal to b...
    {
      while(c>0)              // and while c is greater than zero...
        {
            m = a/b;            // find out how many times b goes into a and set that to m.
            c = a-b*m;          // Then, set 'c' to ('a' minus 'b' as many times as possible)
            if(c!=0)            // If 'c' ends up not being zero...
            {
                a = b;          // make 'a' the new 'b'...
                b = c;          // and make 'b' the new 'c'...
            }
        }                     // and run it again.

      gcf = b;                // Once 'c' is less than or equal to zero, set the GCF to the last value of b.
    }
    else if(b>a)                // Otherwise, if 'b' is actually greater than 'a'...
    {
      while(c>0)              // do the same equation over again, but swap the 'a' and 'b' values.
        {
          m = b/a;
          c = b-a*m;
          if(c!=0)
            {
              b = a;
              a = c;
            }

        }
      gcf = a;
    }
    return gcf;
}

void Fraction::simplify()
{
    numerator = numerator/gcf;                              // Divide the final numerator by the GCF...
    denominator = denominator/gcf;                          // then divide the final denominator by the GCF.
}
Last edited on
And, here's the second file I created that works just fine:

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
#include <iostream>     // Standard iostream include directive
#include <string>       // Used for strings
#include <cstdlib>      // Used for atoi functions

using namespace std;    // Use the standard namespace

class Fraction         // Create a class to store our fractions
{
  public:
    void setInput(int a, int b);
    int findGCF();
    void simplify();
    int getNumerator() {return numerator;};
    int getDenominator() {return denominator;};
  private:
    int denominator;    // Define the structure members
    int numerator;
    string input;
    int gcf;
};

int main()
{
    Fraction first, second, final;      // Define the structure objects
    string answer;                      // Define answer
    bool check;                         // Define boolean variable as part of data input validation

    cout << "\n\n***This program will ask for two fractions.  It will then add them together and display the result,\n"
         << "then show the simplified result.***\n\n";

    final.setInput(53,35);
    cout << "GCF: " << final.findGCF() << endl;
    final.simplify();

    cout << "After being simplified: " << final.getNumerator() << "/" << final.getDenominator() << endl << endl;


  return 0;
}

void Fraction::setInput(int a, int b)
{
    numerator = a;
    denominator = b;
}

int Fraction::findGCF()         // This function finds the GCF
{
  int a, b, c, m;        // Define necessary variables.


  a=numerator;          // Set a to the value of our final numerator to keep the code clean.
  b=denominator;        // Set b to the value of our final denominator to keep the code clean.

    if(a>=b)                    // If a is greater than or equal to b...
    {
      while(c>0)              // and while c is greater than zero...
        {
            m = a/b;            // find out how many times b goes into a and set that to m.
            c = a-b*m;          // Then, set 'c' to ('a' minus 'b' as many times as possible)
            if(c!=0)            // If 'c' ends up not being zero...
            {
                a = b;          // make 'a' the new 'b'...
                b = c;          // and make 'b' the new 'c'...
            }
        }                     // and run it again.

      gcf = b;                // Once 'c' is less than or equal to zero, set the GCF to the last value of b.
    }
    else if(b>a)                // Otherwise, if 'b' is actually greater than 'a'...
    {
      while(c>0)              // do the same equation over again, but swap the 'a' and 'b' values.
        {
          m = b/a;
          c = b-a*m;
          if(c!=0)
            {
              b = a;
              a = c;
            }

        }
      gcf = a;
    }
    return gcf;
}

void Fraction::simplify()
{
    numerator = numerator/gcf;                              // Divide the final numerator by the GCF...
    denominator = denominator/gcf;                          // then divide the final denominator by the GCF.
}


Thanks in advance for any help you can give me!
Last edited on
I am not sure if it is the issue here, but the iinteger c in findGCF is not initialized
Yeah, I noticed that yesterday as well but got distracted and didn't follow up on it. I'll try initializing it to 1 and see how it goes. Thanks for the reminder!
Hello there friend, you realize that your the piece of code in the first post tests the fraction 53/35, on and on again, right?

I added these few lines, just to give the user the chance to set a fraction, and it worked perfectly fine, I'm using Code::Blocks too :D

1
2
3
4
5
6
7
8
9
cout << "Fraction 2: " << second.getNumerator() << "/" << second.getDenominator() << endl;*/

        cout << "Enter num den: ";
        int p, q;
        cin >> p >> q;
        final.setInput(p,q);

        //final.addFract(first, second);
        cout << "\n\nWhen added together your fractions become: " << final.getNumerator() << "/" << final.getDenominator() << endl << endl;
Last edited on
Hello there friend, you realize that your the piece of code in the first post tests the fraction 53/35, on and on again, right?

I added these few lines, just to give the user the chance to set a fraction, and it worked perfectly fine, I'm using Code::Blocks too :D

1
2
3
4
5
6
7
8
9
10
cout << "Fraction 2: " << second.getNumerator() << "/" << second.getDenominator() << endl;*/
        cout << "Enter num den: ";
        int p, q;
        cin >> p >> q;
        final.setInput(p,q);

        //final.addFract(first, second);                                     // Run function to add the fractions together.

        cout << "\n\nWhen added together your fractions become: " << 
final.getNumerator() << "/" << final.getDenominator() << endl << endl;



ljs is right. Typically, uninitialized ints are very large positive integers. It is better to do this change:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if(a>=b)                    // If a is greater than or equal to b...
    {
      while(c>0)              // and while c is greater than zero...
        {
            m = a/b;            // find out how many times b goes into a and set that to m.
            c = a-b*m;          // Then, set 'c' to ('a' minus 'b' as many times as possible)
            if(c!=0)            // If 'c' ends up not being zero...
            {
                a = b;          // make 'a' the new 'b'...
                b = c;          // and make 'b' the new 'c'...
            }
        }                     // and run it again.

      gcf = b;                // Once 'c' is less than or equal to zero, set the GCF to the last value of b.
    }


to

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if(a>=b)                    // If a is greater than or equal to b...
    {
        m = a/b;            // find out how many times b goes into a and set that to m.
            c = a-b*m;
      while(c>0)              // and while c is greater than zero...
        {

                a = b;          // make 'a' the new 'b'...
                b = c;          // and make 'b' the new 'c'...

        }                     // and run it again.

      gcf = b;                // Once 'c' is less than or equal to zero, set the GCF to the last value of b.
    }
Last edited on
Topic archived. No new replies allowed.