C语言 二进制插值找到多项式根总是输出0.00 [关闭]

xxslljrj  于 2023-11-16  发布在  其他
关注(0)|答案(2)|浏览(101)

**已关闭。**此问题需要debugging details。目前不接受回答。

编辑问题以包括desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem。这将帮助其他人回答问题。
3天前关闭。
Improve this question
我使用二进制插值来找到值ab之间的多项式根(用a < b),但输出总是0.00,我真的不能解决它。
下面是我的C代码:

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

float fx(int a3, int a2, int a1, int a0, float x) {
    return a3 * pow(x, 3) + a2 * pow(x, 2) + a1 * x + a0;
}

float binary(int a3, int a2, int a1, int a0, float a, float b, float *result)
{
    float fa = fx(a3, a2, a1, a0, a), fb = fx(a3, a2, a1, a0, b);
    float mid = (a + b) / 2;
    float fmid = fx(a3, a2, a1, a0, mid);
    float root = 0.0;
    if (b - a >= 0.001) {
        if (fa * fb >= 0) {
            *result = 0;
            return 0;
        }
        if (fa * fb < 0)//
        {
            if (fmid == 0) {
                *result = mid;
                return 0;
            }
            else if (fmid * fa > 0) {
                a = mid;
                root = binary(a3, a2, a1, a0, a, b, result);
            }
            else if (fmid * fb > 0) {
                b = mid;
                root = binary(a3, a2, a1, a0, a, b, result);
            }
        }
    }
    *result = mid;
    return 0;
}

int main()
{
    int a3, a2, a1, a0;
    float a, b, result;

    scanf("%d %d %d %d", &a3, &a2, &a1, &a0);
    scanf("%f %f", &a, &b);
    float output = binary(a3, a2, a1, a0, a, b, &result);
    printf("%.2lf", output);
    return 0;
}

字符串
我相信在使用binary函数时,我使用了递归。虽然我成功地通过递归找到了结果,但它没有返回正确的值。在使用VSCode中的调试器时,我观察到我找到的最终值是正确的,但函数没有返回预期的结果。我的测试数据包括a3 = 3, a2 = -1, a1 = -3, a0 = 1。预期的输出是0.33,但实际输出是0.00
请帮帮我!我只是一个一年级的学生,我花了一个晚上试图解决它!

hec6srdp

hec6srdp1#

存在多个问题:

  • 函数binary总是返回0。返回的值不是根值,它存储在*result中,它应该是成功的指示符:例如:如果fx(a)fx(b)具有相同的符号,则函数失败。
  • 您应该返回递归调用的结果,而不是将其存储到root中并忘记它,最后将mid的初始值存储到*result中。
  • 不建议使用具有潜在负值的pow。请改用嵌套乘法。
  • 存在多个冗余测试。
  • 您应该测试scanf()是否无法转换预期的输入值。
  • 测试b - a < 0.001有问题,但与使用%.2f的输出精度一致。您确实提到了约束a < b,但最好使用fabs(b - a) < 0.001,因为它删除了约束,而且更加明确。

以下是修改后的版本:

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

float fx(int a3, int a2, int a1, int a0, float x) {
    return ((a3 * x + a2) * x + a1) * x + a0;
}

int binary(int a3, int a2, int a1, int a0, float a, float b, float *result) {
    float fa = fx(a3, a2, a1, a0, a);
    float fb = fx(a3, a2, a1, a0, b);
    float mid = (a + b) / 2;
    float fmid = fx(a3, a2, a1, a0, mid);

    if (fa == 0) {
        *result = a;
        return 1;
    }
    if (fb == 0) {
        *result = b;
        return 1;
    }
    if (fmid == 0 || fabs(b - a) < 0.001) {
        *result = mid;
        return 1;
    }
    if (fa * fb > 0) {
        // failure: function has the sign sign on boundaries
        *result = mid;
        return 0;
    }
    if (fmid * fa > 0) {
        // interpolate between mid and b
        return binary(a3, a2, a1, a0, mid, b, result);
    } else {
        // interpolate between a and mid
        return binary(a3, a2, a1, a0, a, mid, result);
    }
}

int main() {
    int a3, a2, a1, a0;
    float a, b, result;

    if (scanf("%d %d %d %d", &a3, &a2, &a1, &a0) != 4)
        return 1;
    if (scanf("%f %f", &a, &b) != 2)
        return 1;
    int success = binary(a3, a2, a1, a0, a, b, &result);
    printf("success=%d, result=%.2f\n", success, result);
    return 0;
}

字符串
请注意,上述实现在每个递归步骤重新计算边界值,而使用循环并仅计算中点处的值将更有效。
下面是一个非递归实现:

int binary(int a3, int a2, int a1, int a0, float a, float b, float *result) {
    float fa = fx(a3, a2, a1, a0, a);
    float fb = fx(a3, a2, a1, a0, b);

    if (fa == 0) {
        *result = a;
        return 1;
    }
    if (fb == 0) {
        *result = b;
        return 1;
    }
    if (fa * fb >= 0) {
        // failure: function has the sign sign on boundaries
        *result = 0;
        return 0;
    }

    for (;;) {
        float mid = (a + b) / 2;
        float fmid = fx(a3, a2, a1, a0, mid);

        if (fmid == 0 || fabs(b - a) < 0.001) {
            *result = mid;
            return 1;
        }
        if (fa * fmid > 0) {
            // interpolate between mid and b
            a = mid;
            fa = fmid;
        } else {
            // interpolate between a and mid
            b = mid;
            fb = fmid;
        }
    }
}

7gcisfzg

7gcisfzg2#

binary()在所有情况下都返回0,这是您分配给output变量的值,这就是您打印的内容。您可以return结果并删除result参数,resultroot变量沿着这些行:

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

double fx(int a3, int a2, int a1, int a0, double x) {
    return a3 * pow(x, 3) + a2 * pow(x, 2) + a1 * x + a0;
}

double binary(int a3, int a2, int a1, int a0, double a, double b) {
    double fa = fx(a3, a2, a1, a0, a);
    double fb = fx(a3, a2, a1, a0, b);
    double mid = (a + b)/2;
    double fmid = fx(a3, a2, a1, a0, mid);
    if (fabs(b - a) > 0.001) {
        if (fa * fb >= 0)
            return NAN;
        if (!fmid)
            return mid;
        if(fmid * fa > 0)
            return binary(a3, a2, a1, a0, mid, b);
        if(fmid * fb > 0)
            return binary(a3, a2, a1, a0, a, mid);
    }
    return mid;
}

int main(void) {
    int a3, a2, a1, a0;
    double a, b;
    scanf("%d %d %d %d", &a3, &a2, &a1, &a0);
    scanf("%lf %lf", &a, &b);
    printf("%.2lf\n", binary(a3, a2, a1, a0, a, b));
}

字符串
示例运行:

3 -1 -3 1
-0.5 0.5
0.33


错误情况if (fa * fb >= 0)你可以用一个单独的参数/返回值来处理(见@chgrlie的答案)。这应该会显示你的默认设计。为了显示一些不同的东西,你也可以返回NAN来让调用者知道值是无效的。只有当你的值域中的值确实不同时(比如当你期望一个正结果时,返回一个负值)才这样做。

相关问题