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

Modulus of a really really long number (fmod)

本文关键字:fmod 非常 一个      更新时间:2023-10-16

我想使用 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 %ldn",n);
for(int i=2;i<=n;i++)
{
    fact=fact*i;
    printf("Looping with fact %LFn",fact);
}
printf("Fmod %lf %dn",fmod(fact,denominator),(fmod(fact,denominator)==zero));
while(fmod(fact,denominator)==zero)
{
    fact=fact/10;
    z++;
}
printf("Number of zeroes is %ldn",z);
return z;
}
int main()
{
long n;
long x;
scanf("%ld",&n);
for(int i=0;i<n;i++)
{
    scanf("%ld",&x);
    printf("Calling funcn");
    zeroesInFact(x);
}
return 0;
}

我认为这里的问题是

fmod(事实,分母(给了我阶乘 22 和分母为 10.00(即 0.000(的正确答案。但它给了我 23 的阶乘和 10.00 的分母的错误答案

将此视为数字精度的第一课。类型floatdoublelong double 存储近似值,而不是精确值,这意味着它们通常不适合此类计算。即使它们有足够的精度来获得正确答案,您通常仍然最好使用整数类型,例如 int64_tuint64_t 。有时您甚至有一个 128 位整数类型可用。(例如 __int128可能随Microsoft Visual Studio一起使用(

老实说,我认为您很幸运能够通过22!获得18!的正确答案。

如果long double在您的平台上确实是四倍精度,那么我认为您应该能够计算多达 30! 个。当你使用fmod时,你犯了一个错误 - 你的意思是使用fmodl


你的

第二个精度教训是,当你需要大量的精度时,你的基本数据类型根本不够好。虽然您可以编写自己的数据类型,但最好使用预先存在的解决方案。Gnu 多精度算术库 (GMP( 是一个很好的,快速的库,你可以在 C/C++ 中使用。

或者,您可以切换语言 - 例如 python的整数数据类型是任意精度(但不如GMP快(,因此您甚至不必执行任何特殊操作。Java有BigInteger类来执行此类计算。


你的第三个教训是精确是找到没有的方法。您实际上不需要计算23!的全部荣耀来查找尾随零的数量。您可以小心地组织计算,以丢弃不需要的额外精度。或者,您可以切换到完全不同的方法来获取此数字,例如 Rob 在他的评论中暗示的内容。