我想使用 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 的错误答案
将此视为您关于数字精度的第一课。类型float
, double
, and long double
存储近似值,而不是精确值,这意味着它们通常不适合此类计算。即使它们具有足够的精度来获得正确答案,通常最好还是使用整数数字类型,例如int64_t
and uint64_t
。有时甚至可以使用 128 位整数类型。 (例如。__int128
可能可与 Microsoft Visual Studio 一起使用)
老实说,我认为你很幸运能够得到正确的答案18!
通过22!
.
If long double
在您的平台上确实是四倍精度,您应该能够计算最多30!
, 我认为。你使用的时候犯了一个错误fmod
-- 你打算使用fmodl
.
关于精度的第二个教训是,当您需要大量精度时,您的基本数据类型根本不够好。虽然您可以编写自己的数据类型,但使用预先存在的解决方案可能会更好。这Gnu 多精度算术库 (GMP) 是一个可以在 C/C++ 中使用的又好又快的库。
或者,您可以切换语言 - 例如python
s 整数数据类型是任意精度(但不如 GMP 快),因此您甚至不必执行任何特殊操作。 Java 有BigInteger
进行此类计算的类。
你的第三个教训是精确性,就是找到没有精确性的方法。你实际上不需要计算23!
在其全部荣耀中找到尾随零的数量。您可以小心地组织计算以放弃不需要的额外精度。或者,您可以改用一种完全不同的方法来获取此数字,例如 Rob 在他的评论中暗示的那样。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)