You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于结构体的C语言梯形面积周长计算函数:测试用例未通过

梯形面积计算错误修复

问题描述

给定以下结构体定义:

struct Point {
    double x, y;
};
struct Trapezoid {
    struct Point A,B,C,D;
};

需要实现trapezoids函数,接收梯形数组、数组大小,以及两个空数组,分别存储每个梯形的周长和面积。现有代码在部分测试用例中计算结果不符,测试用例中4个梯形预期面积均为16.50,但实际输出为11.67 36.83 16.50 33.00。

原代码问题分析

  1. 平行边假设错误:原代码默认AB和CD是梯形的平行底边,但测试用例中部分梯形的平行边为AD和BC(如第4个测试用例),导致底边长取值错误。
  2. 高的计算逻辑错误:原代码用对角线BD的长度结合角度正弦值计算高,这不符合梯形高的定义——梯形的高是两平行底边之间的垂直距离,而非对角线相关的推导值。
  3. 浮点数精度处理缺失:直接用==判断斜率是否相等,会因浮点数计算误差导致平行边判断失效。

修复后的代码

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

struct Point {
    double x;
    double y;
};

struct Trapezoid {
    struct Point A, B, C, D;
};

double distance(struct Point p1, struct Point p2) {
    double dx = p2.x - p1.x;
    double dy = p2.y - p1.y;
    return sqrt(dx * dx + dy * dy);
}

// 判断两个浮点数是否相等(考虑精度误差)
bool isEqual(double a, double b) {
    return fabs(a - b) < 1e-8;
}

// 获取直线ax + by + c = 0的参数a、b、c
void getLineParams(struct Point p1, struct Point p2, double *a, double *b, double *c) {
    *a = p2.y - p1.y;
    *b = p1.x - p2.x;
    *c = p2.x * p1.y - p1.x * p2.y;
}

// 计算点到直线的距离
double pointToLineDistance(struct Point p, double a, double b, double c) {
    return fabs(a * p.x + b * p.y + c) / sqrt(a*a + b*b);
}

void trapezoids(struct Trapezoid trapezoids[], int n, double perimeters[], double areas[]) {
    for (int i = 0; i < n; i++) {
        struct Trapezoid t = trapezoids[i];
        // 计算四条边长度,用于周长计算
        double AB = distance(t.A, t.B);
        double BC = distance(t.B, t.C);
        double CD = distance(t.C, t.D);
        double DA = distance(t.D, t.A);

        perimeters[i] = AB + BC + CD + DA;

        // 计算各边的斜率,处理垂直边(用INFINITY标记)
        double slope_AB = isEqual(t.B.x, t.A.x) ? INFINITY : (t.B.y - t.A.y)/(t.B.x - t.A.x);
        double slope_BC = isEqual(t.C.x, t.B.x) ? INFINITY : (t.C.y - t.B.y)/(t.C.x - t.B.x);
        double slope_CD = isEqual(t.D.x, t.C.x) ? INFINITY : (t.D.y - t.C.y)/(t.D.x - t.C.x);
        double slope_DA = isEqual(t.A.x, t.D.x) ? INFINITY : (t.A.y - t.D.y)/(t.A.x - t.D.x);

        double base1, base2, height;
        // 确定平行的对边
        if (isEqual(slope_AB, slope_CD)) {
            // AB与CD平行,作为上下底
            base1 = AB;
            base2 = CD;
            // 计算点C到直线AB的距离作为高
            double a, b, c;
            getLineParams(t.A, t.B, &a, &b, &c);
            height = pointToLineDistance(t.C, a, b, c);
        } else if (isEqual(slope_DA, slope_BC)) {
            // DA与BC平行,作为上下底
            base1 = DA;
            base2 = BC;
            // 计算点B到直线DA的距离作为高
            double a, b, c;
            getLineParams(t.D, t.A, &a, &b, &c);
            height = pointToLineDistance(t.B, a, b, c);
        } else {
            // 非梯形输入,按题目假设可忽略,此处设面积为0
            areas[i] = 0.0;
            continue;
        }

        // 梯形面积公式:(上底+下底)/2 × 高
        areas[i] = 0.5 * (base1 + base2) * height;
    }
}

// 测试用例主函数示例
int main() {
    struct Trapezoid array[] = {
        {{-4,2}, {0.950, 6.950}, {-2.586, 7.657}, {-5.414, 4.828}}, // 45度
        {{-4,2}, {-7.5, 8.062}, {-9.098, 4.830}, {-7.098, 1.366}}, // 120度
        {{-4,2}, {-11, 2}, {-9, -1}, {-5, -1}}, // 180度
        {{-4,2}, {-4, -5}, {-1, -3}, {-1, 1}} // 270度
    };
    double perimeters[4], areas[4];

    trapezoids(array, 4, perimeters, areas);

    for (int i = 0; i < 4; i++) {
        printf("%.2f ", areas[i]);
    }
    // 输出应为:16.50 16.50 16.50 16.50

    return 0;
}

修复说明

  1. 动态识别平行边:通过计算四条边的斜率,结合精度判断,自动识别哪组对边平行,避免固定假设的错误。
  2. 正确计算高:使用点到直线的距离公式,计算平行底边之间的垂直距离,作为梯形的高。
  3. 浮点数精度处理:用isEqual函数判断浮点数是否相等,允许1e-8的误差范围,避免计算误差导致的判断错误。

内容的提问来源于stack exchange,提问作者Irma Ibrović

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 09:20:03