付宁远23373125 1

分析下面代码的运行结果

Pasted image 20250912202136.png

  1. 判别式 d:
    • 理论值应为 1e14 - 2
    • 由于浮点数精度限制,1e14 远大于 2,导致 2 被忽略,d 的计算结果为 9999999.9999999013,存在微小误差。
  2. 大根 x1:
    • 计算为 (-b + d) / (2a),是两个大数相加,结果 10000000.0000000000 是正确的。
  3. 小根 x2:
    • 计算为 (-b - d) / (2a),是两个几乎相等的大数相减,发生了灾难性抵消。
    • d 的微小误差被放大,导致结果 0.0000000997 与理论值 0.0000001 相比,存在显著错误。
      核心问题:直接套用数学公式在计算机上计算时,会因为浮点数的精度限制导致数值不稳定,尤其是在计算小根时,大数相减会严重损失精度。

算法框图

开始
输入a, b, c, e
如果 |a| < e
    如果 |b| < e
        如果 |c| < e
            输出无穷多根
        否则
            输出无根
    否则
        x = -c / b
        输出一个根x
否则
    d = b*b - 4*a*c
    如果 d < -e
        输出无实根
    否则如果 |d| < e
        x = -b / (2*a)
        输出两个相等根x
    否则
        d_sqrt = sqrt(d)
        如果 b >= 0
            q = -0.5 * (b + d_sqrt)
        else
            q = -0.5 * (b - d_sqrt)
        如果 |q| < e
            x1 = -b / (2*a)
            x2 = x1
        否则
            x1 = q / a
            x2 = c / q
        输出两个根x1和x2
结束

代码

#include <stdio.h>  
#include <math.h>  
#include <stdlib.h>  
  
int main() {  
    double a, b, c, e;  
    printf("a, b, c, e: ");  
    scanf("%lf %lf %lf %lf", &a, &b, &c, &e);  
  
    double M = fmax(fmax(fabs(a), fabs(b)), fabs(c));  
    double a1, b1, c1, e1, e2;  
    if (M > 1e100 || M < 1e-100) {  
        a1 = a / M;  
        b1 = b / M;  
        c1 = c / M;  
        e1 = e / M;  
        e2 = e / (M * M);  
    } else {  
        a1 = a;  
        b1 = b;  
        c1 = c;  
        e1 = e;  
        e2 = e;  
    }  
  
    if (fabs(a1) < e1) {  
        if (fabs(b1) < e1) {  
            if (fabs(c1) < e1) {  
                printf("无限根\n");  
            } else {  
                printf("无根\n");  
            }  
        } else {  
            double x = -c1 / b1;  
            printf("一个根: x = %.10e\n", x);  
        }  
    } else {  
        double d1 = b1 * b1 - 4 * a1 * c1;  
        if (d1 < -e2) {  
            printf("无实根\n");  
        } else if (fabs(d1) < e2) {  
            double x = -b1 / (2 * a1);  
            printf("两个相等的根: x1 = x2 = %.10e\n", x);  
        } else {  
            double d_sqrt = sqrt(d1);  
            double q;  
            if (b1 >= 0) {  
                q = -0.5 * (b1 + d_sqrt);  
            } else {  
                q = -0.5 * (b1 - d_sqrt);  
            }  
            double x1, x2;  
            if (fabs(q) < e1) {  
                x1 = -b1 / (2 * a1);  
                x2 = x1;  
            } else {  
                x1 = q / a1;  
                x2 = c1 / q;  
            }  
            printf("两个不同的根: x1 = %.10e, x2 = %.10e\n", x1, x2);  
        }  
    }  
  
    return 0;  
}
Built with MDFriday ❤️