可以找到以下系列的无穷大之和:
1 1/2 1/3 1/4 1/5 ...
根据某位科学家的解释,无穷大是指任何一点都不存在的点,即 inf + x = inf 或 inf~(inf + x)= 0 。因此,基于该理论,使用了以下算法:
float sum=0.0;
for(int i=0;;i++){
if((sum+(1.0/i))==sum)
break;
sum+=(1.0/i);
}
/* print the value of sum */
算法在 C 和 JAVA 中运行,两者都将输出显示为 inf 。分别用 C 和 Java 编写的印刷语句为
printf("%6f",sum);
System.out.println(sum);
修改 之前写的代码(在问题中)有一个错误,因为我键入它,没有复制粘贴。对不起。这就解决了,这是我的问题所在的代码:
float sum=0.0;
for(int i=1;;i++){
if((sum+ (1.0/i))==sum)
break;
sum+=(1.0/i);
}
/*print the value of sum*/
我的一位朋友说他的输出是 C 中的有限小数。但在我的情况下,程序永远不会终止,无论是在 C 还是 Java (此输出来自上面发布的新编辑代码。不要考虑以前的错误的代码和它的输出是“INF”。)我的问题是,这个算法可以接受吗?如果是,那么我想知道导致 C 中不同输出的可能性。感谢。
答案 0 :(得分:8)
算法在C和JAVA中运行,两者都将输出作为inf。
这是因为您的代码中存在错误。您从i == 0
开始。当您计算1.0 / 0
时,您会得到一个INF。
该系列应以i == 1
...
您编辑了问题以修复该特定错误。
即便如此,你仍然永远无法得到无穷大和的正确值。该系列发散(进入无穷大),但考虑到你计算它的方式,你无法到达那里。
最终,您将达到1.0/i
太小而无法更改sum
的点,您将跳出循环。我希望这会在i == Integer.MAX_VALUE
之前发生......但如果它没有,那么你会遇到代码中的另一个错误。如果i
已达到Integer.MAX_VALUE
,那么它将回到Integer.MIN_VALUE
,您将开始将否定条款添加到总和中。糟糕!
实际上,你想要计算的是谐波系列。部分和(对于N个项)收敛到log e N + E,其中E是Euler-Mascheroni常数。
来源:https://en.wikipedia.org/wiki/Harmonic_series_%28mathematics%29#Partial_sums
由此,我们应该能够估计第N个部分和与1.0 / N
之间的差异何时变得足以停止迭代。
最后一点:如果你向相反的方向求和,你会获得更准确的总和;即以非常大的N开始并且将N减少为1进行求和。
答案 1 :(得分:2)
您的代码存在许多问题。你的程序不起作用,它似乎只能工作。
文字0.0
的类型为double
。意味着对sum+(1.0/i)
类型执行计算double
,类型可能比特定系统上的float
更大。您的代码假定float
和double
具有相同的表示形式,因此它是不可移植的。
因此,在计算过程中,结果可能不会太大,这在double
类型上完成,但当您尝试将其显示回float
时,它不适合。而是在所有文字上使用f
前缀,即:1.0f
。或者只是在整个程序中使用double
。
避免神秘的循环。无需在循环体内移动循环条件。你的循环应该看起来像for(int i=0; float_compare(sum+1.0f/i, sum); i++)
,其中float_compare
是比较浮点数的某种方式。像这样:
#include <math.h>
#define EPSILON 0.00001f
inline bool float_compare (float x, float y)
{
return fabsf(result - expectedResult) < EPSILON;
}
答案 2 :(得分:1)
一些注释i的范围很重要 - 整数只有固定的表示。
系列1/1 + 1/2 + 1/3 + 1/4 ......是发散的(wikipedia : sum of recipricals)
int换行的范围,所以你也要添加-1/1 -1/2 ......这将倾向于0。
系列进展到无限非常缓慢,因此计算机可能不是最好的解决方法。