@
@
@ _ @2021-01-11 18:58:10
C++ / C#
@ _ @, 2021-01-11 18:58:10

Why does the program run faster?

Performed an exercise from one book on C ++. The program below receives a number from the user, which will later be the denominator of the fractions that the program will display. It will make up fractions whose value will be less than 1.
In short, if you enter 6, you will first get 1/6 2/6 3/6 4/6 5/6 6/6 as the output.
(Program output: 1/61/31/22/35/61)
After that, the program will multiply the resulting fractions according to the "each with each" principle.

Well, I noticed during the tests that if you enter a very large number (I entered one that exceeded the maximum allowable value (for example, 1111111111111111111111111111111111)), then the time between the output of the next fraction gradually noticeably decreases (for example, if the first fraction is displayed on screen after 5 seconds, the second fraction will be displayed after 3 seconds, etc.).

Why is this happening?

#include <iostream>
#include <cmath>
using namespace std;

class fraction
{
  private:
    int num;
    int denom;
  public:
    fraction(): num(0), denom(0)
    {	}

    fraction(int n, int d): num(n), denom(d)
    {	}

    void getfraction()
    {
      char _;
      cin >> num >> _ >> denom;
    }

    void getfraction(int n, int d)
    {
      num = n;
      denom = d;
    }

    void showfraction()
    {
      lowterms();
      cout << num << '/' << denom;
    }

    void fadd(fraction, fraction);
    void fsub(fraction, fraction);
    void fmul(fraction, fraction);
    void fdiv(fraction, fraction);

    void lowterms();
};

void fraction::fadd(fraction f1, fraction f2)
{
  num = f1.num*f2.denom + f2.num*f1.denom;
  denom = f1.denom * f2.denom;
}

void fraction::fsub(fraction f1, fraction f2)
{
  num = f1.num*f2.denom - f2.num*f1.denom;
  denom = f1.denom * f2.denom;
}

void fraction::fmul(fraction f1, fraction f2)
{
  num = f1.num * f2.num;
  denom = f1.denom * f2.denom;
}

void fraction::fdiv(fraction f1, fraction f2)
{
  num = f1.num * f2.denom;
  denom = f1.denom * f2.num;
}

void fraction::lowterms()
{
  long tnum, tdenom, temp, gcd;
  tnum = labs(num);
  tdenom = labs(denom);
  if(tdenom == 0)
  { cout << "Unavailable denominator!"; exit(1); }
  else if(tnum == 0)
  { num = 0; denom = 1; return; }
  while(tnum != 0)
  {
    if(tnum < tdenom)
    { temp = tnum; tnum = tdenom; tdenom = temp; }
    tnum = tnum - tdenom;
  }
  gcd = tdenom;
  num = num / gcd;
  denom = denom / gcd;
}

int main()
{
  fraction f1, f2, f;
  int denom;
  cin >> denom;
  for(int i = 1; i < denom; i++)
  {
    f.getfraction(i, denom);
    f.showfraction();
  }

  cout << endl;
  for(int i = 0; i < 107; i++)
  { cout << '-'; }
  cout << endl;
  
  for(int i = 1; i < denom; i++)
  {
    f1.getfraction(i, denom);
    f1.showfraction();
    for(int j = 1; j < denom; j++)
    {
      f2.getfraction(j, denom);
      f.fmul(f1, f2);
      f.showfraction();
    }
    cout << endl;
  }
  return 0;
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Mercury13, 2021-01-11
@DaniilOLD

Because you have an inefficient gcd calculation algorithm that works on subtraction, and not on division with a remainder.
Naturally, gcd(1,6) = gcd(1, 6−1=5) = gcd(1, 5−1=4) = gcd(1, 4−1=3) = gcd(1, 3−1= 2) = gcd(1, 2−1=1) = gcd(1, 1−1=0) = 1
gcd(2,6) = gcd(2, 6−2=4) = gcd(2, 4− 2=2) = gcd(2, 2−2=0) = 2
Has nothing to do with arithmetic overflow. It's just that even as a result of overflow rather big numbers turned out.
How it should be: gcd(1,6) = gcd(6, 1%6=1) = gcd(1, 6%1=0) = 1
Similarly for gcd(6,2) - in general, it converges quite quickly.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question