鱼C论坛

 找回密码
 立即注册
查看: 819|回复: 4

[已解决]根据xyz数值用高斯消元法求值

[复制链接]
发表于 2023-8-6 02:21:57 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
已知离散坐标系中几十个空间坐标点(x,y,z),需要拟合曲面方程z=f(x,y),
可以简化假设z=ax^2+by^2+cxy+dx+ey+f,用高斯消元法求a,b,c,d,e,f。

求问如何用c解决这个问题
最佳答案
2023-8-6 02:22:43
问题:根据xyz数值用高斯消元法求值 C\C++交流

你可以使用高斯消元法来解决这个问题。以下是在C++中使用高斯消元法求解曲面方程的示例代码:
#include <iostream>#include <vector>using namespace std;// 高斯消元法求解线性方程组void gauss_elimination(vector<vector<double>>& A, vector<double>& B) {    int n = A.size();    // 步骤1:转换为上三角矩阵    for (int i = 0; i < n; i++) {        if (A[i][i] == 0) {            // 如果主元为0,则进行行交换            for (int j = i + 1; j < n; j++) {                if (A[j][i] != 0) {                    swap(A[i], A[j]);                    swap(B[i], B[j]);                    break;                }            }        }        // 消元操作        for (int j = i + 1; j < n; j++) {            double factor = A[j][i] / A[i][i];            for (int k = i; k < n; k++) {                A[j][k] -= factor * A[i][k];            }            B[j] -= factor * B[i];        }    }    // 步骤2:回代求解    vector<double> X(n);    for (int i = n - 1; i >= 0; i--) {        double sum = 0;        for (int j = i + 1; j < n; j++) {            sum += A[i][j] * X[j];        }        X[i] = (B[i] - sum) / A[i][i];    }    // 输出结果    cout << "解为:";    for (int i = 0; i < n; i++) {        cout << X[i] << " ";    }    cout << endl;}int main() {    // 输入坐标点的数量    int num_points;    cout << "请输入坐标点的数量:";    cin >> num_points;    // 输入坐标点数据    vector<double> x(num_points);    vector<double> y(num_points);    vector<double> z(num_points);    for (int i = 0; i < num_points; i++) {        cout << "请输入第 " << i + 1 << " 个坐标点(x, y, z):";        cin >> x[i] >> y[i] >> z[i];    }    // 构建系数矩阵和常数向量    vector<vector<double>> A(6, vector<double>(6));    vector<double> B(6);    for (int i = 0; i < num_points; i++) {        double x2 = x[i] * x[i];        double y2 = y[i] * y[i];        double xy = x[i] * y[i];        A[0][0] += x2 * x2;        A[0][1] += y2 * x2;        A[0][2] += xy * x2;        A[0][3] += x2;        A[0][4] += xy;        A[0][5] += z[i] * x2;        A[1][1] += y2 * y2;        A[1][2] += xy * y2;        A[1][3] += y2;        A[1][4] += xy;        A[1][5] += z[i] * y2;        A[2][2] += xy * xy;        A[2][3] += xy;        A[2][4] += xy;        A[2][5] += z[i] * xy;        A[3][3] += 1;        A[3][4] += x[i];        A[3][5] += z[i] * x[i];        A[4][4] += 1;        A[4][5] += z[i] * y[i];        A[5][5] += z[i] * z[i];    }    for (int i = 1; i < 6; i++) {        for (int j = 0; j < i; j++) {            A[i][j] = A[j][i];        }    }    // 调用高斯消元法函数求解    gauss_elimination(A, B);    return 0;}
在上述代码中,我使用向量存储了输入的坐标点数据,并根据高斯消元法的步骤构建了系数矩阵A和常数向量B。然后,调用gauss_elimination函数进行高斯消元法求解。

请注意,在输入数据时,你需要按照提示依次输入每个坐标点的x、y、z值。程序会自动根据输入的坐标点数量进行计算。最后,输出解向量X,表示方程中a、b、c、d、e、f的值。

希望这段代码能够帮助你,如有更多问题,请随时提问。

如果回答对你有帮助,请给我一个最佳答案!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-8-6 02:22:36 | 显示全部楼层
高斯消元法是一种用于解决线性方程组的方法,而这个问题是要通过高斯消元法求解曲面方程的系数。我们可以将问题转化为一个线性方程组的形式。

首先,我们需要将每个空间坐标点的信息转化为线性方程。根据假设的曲面方程z=ax^2+by^2+cxy+dx+ey+f,我们可以得到以下线性方程:

1. 第一个点:z1 = a*x1^2 + b*y1^2 + c*x1*y1 + d*x1 + e*y1 + f
2. 第二个点:z2 = a*x2^2 + b*y2^2 + c*x2*y2 + d*x2 + e*y2 + f
3. 第三个点:z3 = a*x3^2 + b*y3^2 + c*x3*y3 + d*x3 + e*y3 + f
...
n. 第n个点:zn = a*xn^2 + b*yn^2 + c*xn*yn + d*xn + e*yn + f

其中,n表示总共有多少个空间坐标点。

将上述方程组写成矩阵形式为 AX = B,其中:

A = | x1^2   y1^2   x1*y1   x1   y1   1 |
    | x2^2   y2^2   x2*y2   x2   y2   1 |
    | x3^2   y3^2   x3*y3   x3   y3   1 |
    | ...    ...    ...     ...  ... ... |
    | xn^2   yn^2   xn*yn   xn   yn   1 |

X = | a |
    | b |
    | c |
    | d |
    | e |
    | f |

B = | z1 |
    | z2 |
    | z3 |
    | ... |
    | zn |

现在,我们需要使用高斯消元法解决这个线性方程组。首先,我们将矩阵A进行行变换,使得A变为上三角矩阵。然后,我们可以通过回代法求解X的值。

具体步骤如下:

1. 对于每一列i(i从1到6),找到第i行及以下行中第i列元素的绝对值最大的行j(j从i到n)。
2. 交换第i行和第j行,使得第i行第i列元素成为当前列绝对值最大的元素。
3. 将第i行以下的每一行,通过消元操作将第i列的元素变为0。具体操作为:对于每一行k(k从i+1到n),计算乘数m = Ak[ i] / Ai[ i](Ak[ i]表示第k行第i列的元素,Ai[ i]表示第i行第i列的元素),然后将第k行的每个元素减去m乘以第i行对应元素的值。
4. 重复步骤1到3,直到矩阵A变为上三角矩阵。
5. 通过回代法求解X的值。具体操作为:从最后一行开始,计算Xi = (Bi - sum(Ai[j]*Xj)(j从i+1到6))/ Ai[ i],然后依次计算前面的Xi,直到计算出X1。

最后,得到的X就是曲面方程z=ax^2+by^2+cxy+dx+ey+f的系数。

希望以上解答能够帮助到你!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2023-8-6 02:22:43 | 显示全部楼层    本楼为最佳答案   
问题:根据xyz数值用高斯消元法求值 C\C++交流

你可以使用高斯消元法来解决这个问题。以下是在C++中使用高斯消元法求解曲面方程的示例代码:
#include <iostream>#include <vector>using namespace std;// 高斯消元法求解线性方程组void gauss_elimination(vector<vector<double>>& A, vector<double>& B) {    int n = A.size();    // 步骤1:转换为上三角矩阵    for (int i = 0; i < n; i++) {        if (A[i][i] == 0) {            // 如果主元为0,则进行行交换            for (int j = i + 1; j < n; j++) {                if (A[j][i] != 0) {                    swap(A[i], A[j]);                    swap(B[i], B[j]);                    break;                }            }        }        // 消元操作        for (int j = i + 1; j < n; j++) {            double factor = A[j][i] / A[i][i];            for (int k = i; k < n; k++) {                A[j][k] -= factor * A[i][k];            }            B[j] -= factor * B[i];        }    }    // 步骤2:回代求解    vector<double> X(n);    for (int i = n - 1; i >= 0; i--) {        double sum = 0;        for (int j = i + 1; j < n; j++) {            sum += A[i][j] * X[j];        }        X[i] = (B[i] - sum) / A[i][i];    }    // 输出结果    cout << "解为:";    for (int i = 0; i < n; i++) {        cout << X[i] << " ";    }    cout << endl;}int main() {    // 输入坐标点的数量    int num_points;    cout << "请输入坐标点的数量:";    cin >> num_points;    // 输入坐标点数据    vector<double> x(num_points);    vector<double> y(num_points);    vector<double> z(num_points);    for (int i = 0; i < num_points; i++) {        cout << "请输入第 " << i + 1 << " 个坐标点(x, y, z):";        cin >> x[i] >> y[i] >> z[i];    }    // 构建系数矩阵和常数向量    vector<vector<double>> A(6, vector<double>(6));    vector<double> B(6);    for (int i = 0; i < num_points; i++) {        double x2 = x[i] * x[i];        double y2 = y[i] * y[i];        double xy = x[i] * y[i];        A[0][0] += x2 * x2;        A[0][1] += y2 * x2;        A[0][2] += xy * x2;        A[0][3] += x2;        A[0][4] += xy;        A[0][5] += z[i] * x2;        A[1][1] += y2 * y2;        A[1][2] += xy * y2;        A[1][3] += y2;        A[1][4] += xy;        A[1][5] += z[i] * y2;        A[2][2] += xy * xy;        A[2][3] += xy;        A[2][4] += xy;        A[2][5] += z[i] * xy;        A[3][3] += 1;        A[3][4] += x[i];        A[3][5] += z[i] * x[i];        A[4][4] += 1;        A[4][5] += z[i] * y[i];        A[5][5] += z[i] * z[i];    }    for (int i = 1; i < 6; i++) {        for (int j = 0; j < i; j++) {            A[i][j] = A[j][i];        }    }    // 调用高斯消元法函数求解    gauss_elimination(A, B);    return 0;}
在上述代码中,我使用向量存储了输入的坐标点数据,并根据高斯消元法的步骤构建了系数矩阵A和常数向量B。然后,调用gauss_elimination函数进行高斯消元法求解。

请注意,在输入数据时,你需要按照提示依次输入每个坐标点的x、y、z值。程序会自动根据输入的坐标点数量进行计算。最后,输出解向量X,表示方程中a、b、c、d、e、f的值。

希望这段代码能够帮助你,如有更多问题,请随时提问。

如果回答对你有帮助,请给我一个最佳答案!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-7 07:55:37 | 显示全部楼层
您好,我可以帮助您用C语言实现高斯消元法求解曲面拟合的问题。

首先,您需要根据给定的空间坐标点(x,y,z),构建一个线性方程组AX=b,其中A是一个6×6的系数矩阵,X是一个6×1的未知数向量,b是一个6×1的常数向量。具体地,您可以将每个坐标点代入方程z=ax^2+by^2+cxy+dx+ey+f,得到一个一次方程,然后将所有的一次方程按照未知数的顺序排列成矩阵形式。例如,如果您有三个坐标点(1,2,3),(2,3,4)和(3,4,5),那么您可以得到以下方程组:

a + 4b + 2c + d + 2e + f = 3
4a + 9b + 6c + 2d + 3e + f = 4
9a + 16b + 12c + 3d + 4e + f = 5

对应的矩阵形式为:

| a | b | c | d | e | f || b |
|---|---|---|---|---|---||---|
| 1 | 4 | 2 | 1 | 2 | 1 || 3 |
| 4 | 9 | 6 | 2 | 3 | 1 || 4 |
| 9 |16 |12 | 3 | 4 | 1 || 5 |

当然,这里只是一个简单的例子,您需要根据您实际的数据来构建方程组。

接下来,您需要用高斯消元法求解这个线性方程组,得到未知数向量X的值。高斯消元法的基本思想是通过行变换将系数矩阵A化为上三角矩阵,并同时对常数向量b进行相同的变换,然后从最后一行开始回代求解每个未知数。具体地,您可以参考以下步骤:

- 第一步:在系数矩阵A的第一列中找到绝对值最大的元素,将其所在行与第一行交换,这样可以避免除零错误和舍入误差。
- 第二步:用第一行的每个元素除以第一行第一列的元素,使得第一行第一列变为1。
- 第三步:用第一行乘以适当的倍数,加到其他行上,使得其他行的第一列变为0。
- 第四步:重复以上步骤,对剩下的子矩阵进行同样的操作,直到系数矩阵A变为上三角矩阵。
- 第五步:从最后一行开始回代求解每个未知数,即用常数向量b减去系数矩阵A中对应位置的乘积,并除以系数矩阵A中对角线上的元素。

希望这些信息对您有所帮助。如果您还有其他问题,欢迎继续与我交流。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2023-8-13 00:56:52 | 显示全部楼层
学习编程中的Ben 发表于 2023-8-6 02:22
问题:根据xyz数值用高斯消元法求值 C\C++交流

你可以使用高斯消元法来解决这个问题。以下是在C++中使用高 ...

感谢大佬,  
现在有个新的问题就是提供的坐标数据点可能含有误差,如果有误差的话就解不出值
请问是否有方法能去掉或者跳过那些误差(提供的坐标点不在函数曲线上)

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-24 03:09

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表