【问题标题】:To Find factorial of large number(number of digits >20)查找大数的阶乘(位数> 20)
【发布时间】:2021-08-11 12:45:46
【问题描述】:

我写了一些 C++ 代码来找到 int n 的阶乘。由于阶乘可能是一个非常大的数字,所以我决定将数字存储在一个向量中。但我的代码没有按预期工作。有些人请指出错误并指导我。我低调的感觉就像我搞砸了指针。 请建议是否有更优化的方法。 感谢社区。​​p>

守则:

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

输出:

10000000000000000000
 
[Done] exited with code=0 in 3.204 seconds

【问题讨论】:

  • multiply 通过值而不是引用来获取其参数 res。当您在 factorial 中调用它时,它会作用于 res 的副本,而原始文件保持不变。
  • 那么,解决方案是什么,如何通过引用传递 res?
  • (*res_size)++; 这不会影响res 的大小,所以它仍然会很快越界。顺便说一句,10000000000000000000!大约有 1.8×10^20 位数。这比您的计算机可能支持的要多一点。
  • 10000000000000000000 不是我所说的,是上面代码的输出。并且(*res_size)++; 不能超出界限,因为它明确检查了 MAX 是一个非常大的数字,并且约束限制中的阶乘允许的最大位数。谢谢你的建议。

标签: c++ pointers vector


【解决方案1】:

我看到一些错误:

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

总计:

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

指针可以远程控制原始值在哪里存储在 ram 中。

而不是在代码中到处复制。

看看这个视频,很不错
Introduction to pointers in C/C++

Pointers and dynamic memory - stack vs heap

mycodeschool

【讨论】:

  • int &amp;res_sizeint* res_size 有什么区别我对前者不是很熟悉。请详细说明。
  • @EduardoMarotoCampos 看到问题的最后一行,我确实要求提供更优化的解决方案,包括重构代码,所以它确实解决了我的一些问题......谢谢
  • @NaturalDemon 非常感谢,但由于不能解决主要问题,我无法将其标记为已回答,因为只能接受一个解决方案作为答案。
  • 我查看了您超链接的内容,但我仍然没有回答 int &amp;res_sizeint* res_size 之间的区别?
  • @Ano_nymous1 看我的回答
【解决方案2】:

固定版本:

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

要通过引用传递,只需在参数类型后添加&amp;。 另请参阅 Why should I not #include <bits/stdc++.h>?Why is "using namespace std;" considered bad practice?

有关按值传递和按引用传递的更多信息,您可以查看此处:https://www.educative.io/edpresso/pass-by-value-vs-pass-by-reference

基本上,按值传递会创建原始类型的副本,而按引用传递会传递对原始副本的引用,因此修改引用就是修改原始值。

此外,指针和引用非常相似,尽管当您想要修改传递给函数的变量时,我会使用引用。更多信息: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

【讨论】:

  • 感谢您的宝贵努力。我一定会考虑你的建议。但是由于我确实参加了竞争性编程,所以我的问题是,在 CP 中使用它(标题和“使用命名空间标准”)是否可行?
  • @Ano_nymous1 “竞争性编程”与正确编写 C++ 有什么关系?请注意,您是在 StackOverflow 上提出问题——没有竞争。此外,正确编写代码会增加其他人帮助您的机会。对于业内最常用的编译器Visual C++,不存在bits 头文件。因此,使用该标头编写代码会使任何试图帮助仅使用 Visual C++ 的人感到烦恼。不要轻率,但如果难以输入一些额外的按键,请考虑参加打字课程。
  • 再一次,StackOverflow 上没有竞争。 here 生成代码的正确方法是正确编写代码。我们看到各种疯狂的宏、不兼容的标头等问题,志愿者必须破译这些程序。为什么不仔细阅读以“CP”编码风格开始的数千个问题,然后那些想自愿参加的人就放弃了。解释中有什么令人反感的?如果使用正确的 C++ 代码,您会得到更多帮助吗?
  • @PaulMcKenzie 感谢您提供的信息,但我从未说过在 SO 上有任何竞争。所以你的论点有点模糊,无论如何谢谢你告诉;)祝你好运
  • @Ano_nymous1 你知道你可以继续做using Digits = std::vector&lt;int&gt;;,而不是先导入向量来跳过std::vector&lt;int&gt;,但继续在任何地方做vector&lt;int&gt;。使用语言为您提供的表现力。
猜你喜欢
  • 1970-01-01
  • 2016-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-07
  • 1970-01-01
相关资源
最近更新 更多