一个非常长的数(fmod)的模数
Modulus of a really really long number (fmod)
我想使用 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 的分母的错误答案
将此视为数字精度的第一课。类型float
、double
和 long double
存储近似值,而不是精确值,这意味着它们通常不适合此类计算。即使它们有足够的精度来获得正确答案,您通常仍然最好使用整数类型,例如 int64_t
和 uint64_t
。有时您甚至有一个 128 位整数类型可用。(例如 __int128
可能随Microsoft Visual Studio一起使用(
老实说,我认为您很幸运能够通过22!
获得18!
的正确答案。
如果long double
在您的平台上确实是四倍精度,那么我认为您应该能够计算多达 30!
个。当你使用fmod
时,你犯了一个错误 - 你的意思是使用fmodl
。
你的
第二个精度教训是,当你需要大量的精度时,你的基本数据类型根本不够好。虽然您可以编写自己的数据类型,但最好使用预先存在的解决方案。Gnu 多精度算术库 (GMP( 是一个很好的,快速的库,你可以在 C/C++ 中使用。
或者,您可以切换语言 - 例如 python
的整数数据类型是任意精度(但不如GMP快(,因此您甚至不必执行任何特殊操作。Java有BigInteger
类来执行此类计算。
你的第三个教训是精确是找到没有的方法。您实际上不需要计算23!
的全部荣耀来查找尾随零的数量。您可以小心地组织计算,以丢弃不需要的额外精度。或者,您可以切换到完全不同的方法来获取此数字,例如 Rob 在他的评论中暗示的内容。
- OpenGL大的3D纹理(>2GB)非常慢
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 为什么std::互斥需要很长的、非常不规则的时间来共享
- G++ C++17 类模板参数推导在非常特殊的情况下不起作用
- 使用浮点数和双精度数的非常小数字的数学
- 在打开多个其他窗口时使用全屏窗口时帧速率非常低
- 我从int x[3]得到的一个非常奇怪的输出;
- 反向迭代器在C++中非常奇怪的行为
- 将非常大的 int 转换为双倍,在某些计算机上会损失精度
- 我的自定义使用 std::unordered_map 的性能非常慢
- ifstream 尝试读取 9 到 13 之间的无符号字符时非常奇怪的行为
- 一个非常简单的win32套接字代码,但工作错误
- 非常快速地阅读 CSV 文件
- Fmod 函数清楚地输出一个预期的双精度值,但 if(fmod == 预期的双精度值)的计算结果不是 true
- max_element() 给出非常奇怪的错误消息
- 将 mmap 内存用于开销非常低的循环缓冲区
- 内存映射文件访问非常慢
- 超过CPU时间限制:当MPI_Sent一个非常大的int*时
- QtWebengine 5.7.1的性能非常慢
- 一个非常长的数(fmod)的模数