为什么这些奇怪的数字代码失败了?

时间:2015-02-25 18:38:01

标签: c

我编写了一个函数来查找数字a的立方根,使用Newton-Raphson方法找到函数f(x)= x ^ 3 - a的根。

#include <stdio.h>
#include <math.h>

double cube_root(double a)
{
    double x = a;
    double y;
    int equality = 0;

    if(x == 0)
    {
        return(x);
    }

    else
    {
        while(equality == 0)
        {
            y = (2 * x * x * x + a) / (3 * x * x);

            if(y == x)
            {
                equality = 1;
            }

            x = y;

        }

    return(x);

    }
}

f(x) for a = 20 (blue) and a = -20 (red) http://graphsketch.com/?eqn1_color=1&eqn1_eqn=x*x*x%20-%2020&eqn2_color=2&eqn2_eqn=x*x*x%20%2B%2020&eqn3_color=3&eqn3_eqn=&eqn4_color=4&eqn4_eqn=&eqn5_color=5&eqn5_eqn=&eqn6_color=6&eqn6_eqn=&x_min=-8&x_max=8&y_min=-75&y_max=75&x_tick=1&y_tick=1&x_label_freq=5&y_label_freq=5&do_grid=0&bold_labeled_lines=0&line_width=4&image_w=850&image_h=525

代码似乎运行良好,例如它计算338947578237847893823789474.324623784的立方根很好,但奇怪的是一些数字失败,例如4783748237482394?代码似乎进入无限循环,必须手动终止。

任何人都可以解释为什么代码应该在这个数字上失败?我已经在图表中显示,使用a的起始值,此方法应始终保持更近和更近的估计,直到两个值等于工作精度。因此,我对这个数字并不感到特别。

2 个答案:

答案 0 :(得分:2)

除了发布错误的公式......

您正在执行浮点运算,浮点运算具有舍入误差。即使有舍入错误,你也会非常接近一个立方根,但你不会准确到达那里(通常立方根是不合理的,浮点数是合理的)。

一旦你的x非常接近立方根,当你计算y时,你应该得到与x相同的结果,但是由于舍入错误,你可能得到非常接近x的东西,但是稍微不同。所以x!= y。然后你用y开始进行相同的计算,你可能得到x作为结果。因此,您的结果将永远在两个值之间切换。

你可以用三个数字x,y和z做同样的事情,当z == y或z == x时退出。这更有可能停止,通过一些数学,你甚至可以证明它将永远停止。

最好计算x的变化,并确定该变化是否足够小,以便下一步不会改变x,除了舍入误差。

答案 1 :(得分:1)

不应该是:

y = x - (2 * x * x * x + a)/(3 * x * x);