【问题标题】:Recursive factorial function producing incorrect results on "22!" [duplicate]递归阶乘函数在“22!”上产生不正确的结果[复制]
【发布时间】:2017-10-04 05:07:28
【问题描述】:

我正在制作一个小的阶乘函数来帮助我为函数做一些数学运算。

#include<iostream>
using std::cout;
using std::endl;
class HandsShaking{
    private:
    unsigned long long fac(int n){
        return fac(n, 1);
    }

    unsigned long long fac(unsigned long long n, unsigned long long ret){
        if(n == 1){
            return ret;
        }else{
            return fac(n-1, ret*n);
        }
    }

   public:
   unsigned long long countPerfect(unsigned long long n){
        unsigned long long m = n/2;
        cout<<fac(n)<<endl;
        cout<<(fac(m+1)*fac(m))<<endl;
        return fac(n)/(fac(m+1)*fac(m));
    }
};

我到处都在使用尾递归和无符号长整数,所以我怀疑它是否溢出。

我没有把函数和定义分开,但是我提交的(count perfect函数)指定了一个文件。

该功能似乎对 22 以内的所有数字都有效,但对之后的所有数字都无效。

【问题讨论】:

  • unsigned long long的范围是多少?或std::numeric_limit&lt;unsigned long long&gt;::max()It possibly overflows on your system.。类似问题:stackoverflow.com/questions/236335/…
  • 22!大于2⁶⁴。除非unsigned long long 在您的系统上是 128 位(或更多)(这极不可能),否则您的计算就会溢出。
  • 相当确定它的 64 位 1.8 * 10^19 包含 22!超出范围。问题是我仍然需要 fac 才能工作到 50!而且我不知道任何更大的数字类型。
  • 那我建议你到处找一个库来帮助你(或者实现你自己的大整数类)。在 Google 上搜索“C++ 大整数库”应该会让您朝着正确的方向开始。
  • 50!是 3.041409320171338e64 (除非我的 linux 计算器失败了,但听起来很合理)并且需要大约 215 位来编码为完整整数。以防万一您在某些特定公式中需要它,可能有很小的机会将其简化以使其回到常见的整数范围(例如 (n+m)!/n! 用于小 m)。如果您使用一些通用数学辅助函数,那么您需要实现(或更确切地说是使用)任意精度库。 (不清楚为什么要使用递归,因为从编程的角度来看,这会使fac(..) 代码变得更糟,这是一些练习吗?)

标签: c++ factorial


【解决方案1】:

您可以将Boost.Multiprecision 用于此类任务。

#include <iostream>

#include <boost/multiprecision/cpp_int.hpp>

using boost::multiprecision::cpp_int;

cpp_int factorial(cpp_int x)
{
    if (x == cpp_int{1}) return cpp_int{1};
    return x*factorial(x-1);
}

int main()
{
    cpp_int n{22};
    std::cout << factorial(n) << '\n';
}

Live example

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-06
    • 1970-01-01
    • 2017-05-07
    • 2015-04-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多