问题描述
该程序将查找数字阶乘中的位数
#include <stdio.h>
#include <math.h>
int main()
{
int n = 0,i,count = 0,dig ;
double sum = 0,fact;
scanf("%d",&n );
for(i=1;i<=n;i++)
{
sum = sum + log(i);
}
fact = (exp(sum));
while(fact!=0)
{
dig = ((int)fact%10);
count++;
fact = floor(fact/10);
}
printf("%d\n",count);
return 0;
}
请随意发表评论,以改进此代码,因为我在编码方面还没有广泛的经验。
解决方法
您的代码花了这么长时间的原因是,一旦n
达到约180,fact
的值就会变得太大而无法容纳在双精度浮点变量中。执行此行时:
fact = (exp(sum));
您基本上是将fact
设置为无穷大。结果,以下while()
循环永远不会终止。
在代码中计算对数也没有多大意义。只会减慢速度。只需在double
变量中计算阶乘,并在变量太大时将其重置即可。像这样:
int factorial_digit_count(int n) {
int i,nd=1;
double f = 1.0;
for (i=2; i<=n; i++) {
f *= i;
if (f > 1.0E+100) {
f /= 1.0E+100;
nd += 100;
}
}
while (f > 1.0E+10) {
f /= 1.0E+10;
nd += 10;
}
while (f >= 10.0) {
f /= 10.0;
nd++;
}
return nd;
}
,
假设您不想使用任何数学计算,但想通过自己的方式“蛮力”操作,这将缩短我的运行时间(并主要清理代码)。
#include <stdio.h>
#include <math.h>
int main()
{
int n,fact = 1;
scanf("%d",&n );
for (int i = 1; i < n; i++)
fact *= i;
int sum = 0;
while (fact != 0)
{
fact /= 10;
sum++
}
printf("%d\n",count);
return 0;
}
希望这能回答您的问题,祝您好运!
,数字的基数b
与该数字的基数b
之间存在简单的关系:
len(repr(x,b)) = 1 + floor(log(x,b))
尤其是在以10为底的x中,数字的位数为1 + floor(log10(x))
。 (要了解为什么是这种情况,请查看该公式的幂为10的结果。)
现在,a×b
的对数是a
和b
的对数之和。因此n!
的对数就是1到n
的整数的对数之和。如果我们以10为底进行计算,则可以轻松提取n!
的十进制扩展长度。
换句话说,如果将每个值的log10
而不是log
求和,则可以摆脱:
fact = (exp(sum));
和
while(fact!=0)
{
dig = ((int)fact%10);
count++;
fact = floor(fact/10);
}
并仅输出1 + floor(sum)
。
理论上,这可能会产生舍入误差。但是,您需要做很多对数运算才能使误差项传播到足以在计算中产生误差的程度。 (并不是说它不可能发生。但是如果发生,n
确实是一个很大的数字。)