一个非常长的数字的模数(fmod)

时间:2012-05-04 14:49:33

标签: c++ range

我想使用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

的错误答案

1 个答案:

答案 0 :(得分:3)

考虑这是数学精度的第一课。类型floatdoublelong double存储近似值,而非精确值,这意味着它们通常不适合此类计算。即使他们有足够的精确度来获得正确答案,你通常也会更好地使用整数数字类型,例如int64_tuint64_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在评论中暗示的内容。