golang实现一元二次方程

一元二次方程:y = a * x^2 + b * x + c,曲线类似下面这样。

用途:仪器参数校准、轨迹预测、数据生成。

多个点,使用最小二乘法拟合二次函数方程:

go 复制代码
root@iZwz99zhkxxl5h6ecbm2xwZ:~/temp# cat main.go 
package main

import (
	"fmt"
	"math"
)

func main() {
	// 输入多个离散点的坐标
	x := []float64{1.8, 2, 3}
	y := []float64{2, 3, 5.5}

	// 计算所需的统计量
	n := float64(len(x))
	sumX := 0.0
	sumX2 := 0.0
	sumX3 := 0.0
	sumX4 := 0.0
	sumY := 0.0
	sumXY := 0.0
	sumX2Y := 0.0
	for i := 0; i < len(x); i++ {
		sumX += x[i]
		sumX2 += math.Pow(x[i], 2)
		sumX3 += math.Pow(x[i], 3)
		sumX4 += math.Pow(x[i], 4)
		sumY += y[i]
		sumXY += x[i] * y[i]
		sumX2Y += math.Pow(x[i], 2) * y[i]
	}

	// 构建方程组的系数矩阵 A 和向量 b
	A := [][]float64{
		{n, sumX, sumX2},
		{sumX, sumX2, sumX3},
		{sumX2, sumX3, sumX4},
	}
	b := []float64{sumY, sumXY, sumX2Y}

	// 求解线性方程组 Ax = b
	coeffs := gaussianElimination(A, b)

	// 交换 coeffs[0] 和 coeffs[2] 的值
	coeffs[0], coeffs[2] = coeffs[2], coeffs[0]

	// 输出拟合得到的一元二次方程的系数
	// 注意 coeffs[0] 是 a, coeffs[1] 是 b, coeffs[2] 是 c
	fmt.Printf("一元二次方程的拟合结果: y = %.2fx^2 + %.2fx + %.2f\n", coeffs[0], coeffs[1], coeffs[2])

	// 验证计算结果
	for i := 0; i < len(x); i++ {
		expectedY := coeffs[0]*math.Pow(x[i], 2) + coeffs[1]*x[i] + coeffs[2]
		fmt.Printf("x = %.2f, expected y = %.2f, actual y = %.2f\n", x[i], expectedY, y[i])
	}
}

// gaussianElimination 函数使用高斯消元法求解线性方程组 Ax = b
func gaussianElimination(A [][]float64, b []float64) []float64 {
	n := len(A)
	augmented := make([][]float64, n)
	for i := 0; i < n; i++ {
		augmented[i] = make([]float64, n+1)
		copy(augmented[i], A[i])
		augmented[i][n] = b[i]
	}

	// 前向消元
	for i := 0; i < n; i++ {
		// 部分主元法,找到最大元素并交换行
		maxRow := i
		for j := i + 1; j < n; j++ {
			if math.Abs(augmented[j][i]) > math.Abs(augmented[maxRow][i]) {
				maxRow = j
			}
		}
		augmented[i], augmented[maxRow] = augmented[maxRow], augmented[i]

		for j := i + 1; j < n; j++ {
			factor := augmented[j][i] / augmented[i][i]
			for k := i; k <= n; k++ {
				augmented[j][k] -= factor * augmented[i][k]
			}
		}
	}

	// 回代求解
	coeffs := make([]float64, n)
	for i := n - 1; i >= 0; i-- {
		coeffs[i] = augmented[i][n]
		for j := i + 1; j < n; j++ {
			coeffs[i] -= augmented[i][j] * coeffs[j]
		}
		coeffs[i] /= augmented[i][i]
	}
	return coeffs
}

func printMatrix(matrix [][]float64) {
	for i := 0; i < len(matrix); i++ {
		for j := 0; j < len(matrix[0]); j++ {
			fmt.Printf("%.2f ", matrix[i][j])
		}
		fmt.Println()
	}
}
root@iZwz99zhkxxl5h6ecbm2xwZ:~/temp# go run main.go 
一元二次方程的拟合结果: y = -2.08x^2 + 12.92x + -14.50
x = 1.80, expected y = 2.00, actual y = 2.00
x = 2.00, expected y = 3.00, actual y = 3.00
x = 3.00, expected y = 5.50, actual y = 5.50
root@iZwz99zhkxxl5h6ecbm2xwZ:~/temp#

三个点,唯一确定1个一元二次方程:

go 复制代码
root@iZwz99zhkxxl5h6ecbm2xwZ:~/temp/zz# cat main.go 
package main

import (
	"fmt"
	"math"
)

func main() {
	// 输入三个点的坐标
	x1, y1 := 1.8, 2.0
	x2, y2 := 2.0, 3.0
	x3, y3 := 3.0, 5.5

	// 计算方程组的系数矩阵的行列式和替换列后的行列式
	detA := determinant([][]float64{
		{x1 * x1, x1, 1},
		{x2 * x2, x2, 1},
		{x3 * x3, x3, 1},
	})
	detA1 := determinant([][]float64{
		{y1, x1, 1},
		{y2, x2, 1},
		{y3, x3, 1},
	})
	detA2 := determinant([][]float64{
		{x1 * x1, y1, 1},
		{x2 * x2, y2, 1},
		{x3 * x3, y3, 1},
	})
	detA3 := determinant([][]float64{
		{x1 * x1, x1, y1},
		{x2 * x2, x2, y2},
		{x3 * x3, x3, y3},
	})

	// 求解 a, b, c
	a := detA1 / detA
	b := detA2 / detA
	c := detA3 / detA

	fmt.Printf("二次曲线的方程为: y = %.2fx^2 + %.2fx + %.2f\n", a, b, c)
}

// determinant 函数用于计算矩阵的行列式
func determinant(A [][]float64) float64 {
	if len(A) == 2 {
		return A[0][0]*A[1][1] - A[0][1]*A[1][0]
	}
	det := 0.0
	for i := 0; i < len(A); i++ {
		minor := minorMatrix(A, 0, i)
		det += A[0][i] * math.Pow(-1, float64(i)) * determinant(minor)
	}
	return det
}

// minorMatrix 函数用于计算矩阵 A 去掉第 r 行第 c 列后的子矩阵
func minorMatrix(A [][]float64, r int, c int) [][]float64 {
	minor := make([][]float64, len(A)-1)
	for i := 0; i < len(A)-1; i++ {
		minor[i] = make([]float64, len(A)-1)
	}
	for i := 0; i < len(A); i++ {
		if i < r {
			for j := 0; j < len(A); j++ {
				if j < c {
					minor[i][j] = A[i][j]
				} else if j > c {
					minor[i][j-1] = A[i][j]
				}
			}
		} else if i > r {
			for j := 0; j < len(A); j++ {
				if j < c {
					minor[i-1][j] = A[i][j]
				} else if j > c {
					minor[i-1][j-1] = A[i][j]
				}
			}
		}
	}
	return minor
}
root@iZwz99zhkxxl5h6ecbm2xwZ:~/temp/zz# go run main.go 
二次曲线的方程为: y = -2.08x^2 + 12.92x + -14.50
root@iZwz99zhkxxl5h6ecbm2xwZ:~/temp/zz#
相关推荐
好好沉淀4 分钟前
Elasticsearch 中获取返回匹配记录总数
开发语言·elasticsearch
东东51612 分钟前
基于vue的电商购物网站vue +ssm
java·前端·javascript·vue.js·毕业设计·毕设
2301_7657031414 分钟前
C++与自动驾驶系统
开发语言·c++·算法
MediaTea18 分钟前
<span class=“js_title_inner“>Python:实例对象</span>
开发语言·前端·javascript·python·ecmascript
她说..18 分钟前
策略模式+工厂模式实现审批流(面试问答版)
java·后端·spring·面试·springboot·策略模式·javaee
鹿角片ljp19 分钟前
力扣9.回文数-转字符双指针和反转数字
java·数据结构·算法
skywalker_1119 分钟前
网络编程篇
java·网络协议·网络编程
热爱编程的小刘27 分钟前
Lesson04---类与对象(下篇)
开发语言·c++·算法
毕设源码-朱学姐30 分钟前
【开题答辩全过程】以 基于Java的九价疫苗预约系统为例,包含答辩的问题和答案
java·开发语言
雨季66639 分钟前
Flutter 三端应用实战:OpenHarmony “微光笔记”——在灵感消逝前,为思想点一盏灯
开发语言·javascript·flutter·ui·dart