我想使用Cpp找到阶乘中的零个数。问题是当我使用非常大的数字时。
#include <stdio.h>
#include <math.h>
long zeroesInFact(long n)
{
long double fact=1;
long double denominator=10.00;
long double zero=0.0000;
long z=0;
printf("Strating loop with n %ld\n",n);
for(int i=2;i<=n;i++)
{
fact=fact*i;
printf("Looping with fact %LF\n",fact);
}
printf("Fmod %lf %d\n",fmod(fact,denominator),(fmod(fact,denominator)==zero));
while(fmod(fact,denominator)==zero)
{
fact=fact/10;
z++;
}
printf("Number of zeroes is %ld\n",z);
return z;
}
int main()
{
long n;
long x;
scanf("%ld",&n);
for(int i=0;i<n;i++)
{
scanf("%ld",&x);
printf("Calling func\n");
zeroesInFact(x);
}
return 0;
}
我认为这里的问题是
FMOD(事实上,分母) 给出了因子22和分母为10.00(即0.000)的正确答案。 但它给出了23的阶乘和分母为10.00
的错误答案答案 0 :(得分:3)
考虑这是数学精度的第一课。类型float
,double
和long double
存储近似值,而非精确值,这意味着它们通常不适合此类计算。即使他们有足够的精确度来获得正确答案,你通常也会更好地使用整数数字类型,例如int64_t
和uint64_t
。有时您甚至可以使用128位整数类型。 (例如__int128
可能适用于Microsoft Visual Studio)
老实说,我认为你很幸运能通过18!
获得22!
的正确答案。
如果long double
在您的平台上确实是四倍精度,我认为您应该能够计算最多30!
。使用fmod
时出错了 - 您打算使用fmodl
。
你精确的第二课是当你需要很多时,你的基本数据类型就不够好了。虽然您可以编写自己的数据类型,但最好使用预先存在的解决方案。 Gnu Multiple Precision算术库(GMP)是一个很好的,可以在C / C ++中使用的快速库。
或者,您可以切换语言 - 例如python
整数数据类型是任意精度(但不如GMP快),因此您甚至不需要做任何特殊的事情。 Java有BigInteger
类来进行这样的计算。
你的第三个教训就是精确就是找不到办法。实际上,您并不需要在其全部荣耀中计算23!
来查找尾随零的数量。小心,您可以组织计算以丢弃您不需要的额外精度。或者,您可以切换到一种完全不同的获取此数字的方法,例如Rob在评论中暗示的内容。