这个算法是否可以找到一系列可接受的无穷大的总和?

时间:2016-03-08 07:13:21

标签: java c algorithm math

可以找到以下系列的无穷大之和:

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 中不同输出的可能性。感谢。

3 个答案:

答案 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)

您的代码存在许多问题。你的程序不起作用,它似乎只能工作。

  • Never compare float numbers for equality
  • 计算机不能除以零。
  • 文字0.0的类型为double。意味着对sum+(1.0/i)类型执行计算double,类型可能比特定系统上的float更大。您的代码假定floatdouble具有相同的表示形式,因此它是不可移植的。

    因此,在计算过程中,结果可能不会太大,这在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。

系列进展到无限非常缓慢,因此计算机可能不是最好的解决方法。