-1

I wrote some c++ code to find the factorial of int n. As factorial can be a very large number, so I decided to store the number in a vector. But My Code is not working as expected. Some please point out the bug and guide me. I lowkey feel like I messed with pointers. And Please suggest if there is a more optimal approach for this. Thanks Community.

The Code:

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using std::cout;
    using std::endl;
    using Digits = std::vector<int>;
    
    //define the length of the array, should be the maximum number of digits in the factorial(n)
    #define MAX 20
    
    void multiply(int x,Digits res,int res_size){
      int carry=0;
      for(int i=0;i<res_size;i++){
          int prod=carry+ x*res[i];
          res[i] = prod%10;
          carry = prod/10;
      }
    
      while(carry){
          res[res_size] = carry%10;
          carry/=10;
          (res_size)++;
      }
    }
    
    Digits factorial(int n){
      Digits res(MAX);  
      res[0] = 1;
      int res_size=1;
      for(int i=2;i<=n;i++){
          multiply(i,res,res_size);
      }
      reverse(res.begin(),res.end());
      return res;
    }
    
    int main(){
      for(auto i: factorial(20)){
        cout << i;     
      }cout << endl;
      return 0;
    }

The Output:

10000000000000000000
 
[Done] exited with code=0 in 3.204 seconds
Ano_nymous1
  • 11
  • 1
  • 7
  • 2
    `multiply` takes its argument `res` by value, not by reference. When you call it in `factorial`, it acts on a copy of `res`, leaving the original unchanged. – Nathan Pierson May 22 '21 at 15:37
  • So, what is the solution, how can I pass res by reference? – Ano_nymous1 May 22 '21 at 15:54
  • `(*res_size)++;` This does not affect the size of `res`, so it will still go out of bounds very quickly. By the way, 10000000000000000000! has about 1.8×10^20 digits. This is a bit more than your computer is likely to support. – n. m. could be an AI May 22 '21 at 16:02
  • 10000000000000000000 was not what I called, it is the output of the above code. And `(*res_size)++;` cannot go out of bound as it is explicitly checked that MAX is a very large number and the maximum number of digits a factorial in the constraints limit allow. Thank You for your suggestion. – Ano_nymous1 May 22 '21 at 16:14

2 Answers2

1

Fixed version:

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

//define the length of the array, should be the maximum number of digits in the factorial(n)
#define MAX 20

void multiply(int x, vector<int>& res, int* res_size) {
    int carry = 0;
    for (int i = 0; i < *res_size; i++) {
        int prod = carry + x * res[i];
        res[i] = prod % 10;
        carry = prod / 10;
    }

    while (carry) {
        res[*res_size] = carry % 10;
        carry /= 10;
        (*res_size)++;
    }
}

vector<int> factorial(int n) {
    vector<int> res(MAX);
    res[0] = 1;
    int res_size = 1;
    for (int i = 2; i <= n; i++) {
        multiply(i, res, &res_size);
    }
    return res;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    for (auto i : factorial(20)) {
        cout << i;
    }cout << endl;
    return 0;
}

To pass by reference, simply add an & after the type of a parameter. Also, see Why should I not #include <bits/stdc++.h>? and Why is "using namespace std;" considered bad practice?.

For more info on pass-by-value and pass-by-reference, you can look here: https://www.educative.io/edpresso/pass-by-value-vs-pass-by-reference.

Basically, passing by value creates a copy of the original type, wheras passing by reference passes a reference to the original copy, so modifying the reference is modifying the original value.

Also, pointers and references are very similar, although I would use references when you want to modify a variable you are passing to a function. More on this: https://www.tutorialspoint.com/pointers-vs-references-in-cplusplus#:~:text=References%20are%20used%20to%20refer,to%20store%20address%20of%20variable.&text=A%20reference%20shares%20the%20same,and%20size%20on%20the%20stack.

  • Thank You sir for your valuable efforts. I will surely look into your suggestions. But as I do participate in Competitive Programming, so my question is, Is it(header and "using namespace std") feasible to use in CP? – Ano_nymous1 May 22 '21 at 15:59
  • @Ano_nymous1 What does "Competitive Programming" have to do with writing the C++ properly? Note that you are asking the question on StackOverflow -- there is no competition going on. In addition, writing the code correctly increases the chances that others can help you. That `bits` header file does not exist for the most used compiler in the industry, `Visual C++`. Thus writing your code using that header makes it an annoyance for anyone attempting to help who only use Visual C++. Not to be flippant, but consider taking a typing course if it's difficult to type in a few extra keystrokes. – PaulMcKenzie May 22 '21 at 16:25
  • And again, there is no competition on StackOverflow. The proper way to produce the code *here* is to write it correctly. We see all kinds of questions with crazy macros, incompatible headers, etc., and the volunteer has to decipher these programs. Why not peruse the many thousands of questions that start off with the "CP" coding style, and then the ones who would like to volunteer just give up. What in the explanation is offensive? That you would get more help if proper C++ code were used? – PaulMcKenzie May 22 '21 at 16:48
  • @PaulMcKenzie Thanks for the information, but I never said that there is any competition on SO. So your argument is kind of vague, anyways Thanks for telling ;) Good Luck – Ano_nymous1 May 22 '21 at 16:52
  • @Ano_nymous1 you know you could go ahead and do `using Digits = std::vector;` instead of first importing vector to skip doing `std::vector` but keep doing `vector` everywhere. Use the expressiveness the language gives you to your benefit. – r_ahlskog May 22 '21 at 16:57
  • @r_ahlskog I'll reflect the changes in the code, I didn't know about these features. Thank You very much – Ano_nymous1 May 22 '21 at 16:59
1

i see some errors:

#define MAX 20

    void multiply(int x,vector<int> res,int* res_size){ // should be .. void multiply(int x,vector<int> res,int &res_size)
      int carry=0;
      for(int i=0;i<*res_size;i++){
          int prod=carry+ x*res[i];
          res[i] = prod%10;
          carry = prod/10;
      }
    
      while(carry){
          res[*res_size] = carry%10;
          carry/=10;
          (*res_size)++;
      }
    }
    
    vector<int> factorial(int n){
      vector<int> res(MAX);
      res[0] = 1;
      int res_size=1;
      for(int i=2;i<=n;i++){
          multiply(i,res,&res_size); // should be ... multiply(i,res,res_size)
      }
      return res;
    }

total:

void multiply(int x,vector<int> res,int &res_size){
cout << &res_size<< endl; // print address of "res_size"
  int carry=0;
  for(int i=0;i<res_size;i++){
      int prod=carry+ x*res[i];
      res[i] = prod%10;
      carry = prod/10;
  }

  while(carry){
      res[res_size] = carry%10;
      carry/=10;
      (res_size)++;
  }
}

vector<int> factorial(int n){
  vector<int> res(MAX);
  res[0] = 1;
  int res_size=1;
  for(int i=2;i<=n;i++){
      multiply(i,res,res_size);
  }
  return res;
}




cout << &res_size<< endl; // prints out the address where the value is stored.

int* res_size // stores the reference ( adddress )

Pointers

#include <iostream>
using namespace std;

    int main ()
    {
      int firstvalue, secondvalue;
      int * mypointer;
    
      mypointer = &firstvalue;
      *mypointer = 10;
      mypointer = &secondvalue;
      *mypointer = 20;
      cout << "firstvalue is " << firstvalue << '\n';
      cout << "secondvalue is " << secondvalue << '\n';
      return 0;
    }

pointers provide a remote control to the original value where it's stored in the ram.

instead of making copies everywhere in your code.

check out this video, it's very good
Introduction to pointers in C/C++

Pointers and dynamic memory - stack vs heap

mycodeschool

NaturalDemon
  • 934
  • 1
  • 9
  • 21
  • what is the difference between `int &res_size` and `int* res_size` I am not quite familiar with the former one. Please elaborate. – Ano_nymous1 May 22 '21 at 16:16
  • @EduardoMarotoCampos see the last line of the question, I did ask for a more optimal solution, including refactoring the code, so it does solve some of my problems...Thank You – Ano_nymous1 May 22 '21 at 16:31
  • @NaturalDemon thank you very much, but as does not solve the main problem, I cannot mark it as answered, as only one solution can be accepted as an Answer. – Ano_nymous1 May 22 '21 at 16:32
  • I checked out the content you hyperlinked, yet still, I am unanswered about the difference between `int &res_size` and `int* res_size`? – Ano_nymous1 May 22 '21 at 16:34
  • @Ano_nymous1 see my answer –  May 22 '21 at 16:35
  • @Ano_nymous1, check the videos in my answer and things become clear, that guy explains it very well visually, "pointers" and "stack vs heap", "stack frames" ... how stuff works on C++. – NaturalDemon May 22 '21 at 16:38
  • @Ano_nymous1 basically, every time a method / function gets executed, the entire function is copied and formatted with the data in byte code to the ram from the program code and deleted when the function/methods exits, so if you have a value / data of any type in your main or even higher, you provide the address of that value to the function / method so it can be modified. in recursive coding more than 1 copy of the function exist in ram. – NaturalDemon May 22 '21 at 16:44
  • @Ano_nymous thank you, my friend, I have already watched the mycodeschool's(humblefool) video. My query was just to ask, Is there any difference between passing argument as reference instead of a pointer. Thank You – Ano_nymous1 May 22 '21 at 16:54
  • http://www.cpp.sh/4t43n check it out yourself, a pointer stores the address and a reference provides the address of the data, i guess it's a programmers choice, passing by reference is faster in my opinion, otherwise you would need to write: myclass->mydata, passing by reference: myclass.mydata. passing by reference save you 1 line of code, creating the pointer and saving it's reference. – NaturalDemon May 22 '21 at 17:02