【发布时间】: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<unsigned long long>::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(..)代码变得更糟,这是一些练习吗?)