登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  Golang >  Go问答

Go Gonum Hermite 求积为什么包含权函数约定

来源:17golang原创

时间:2026-10-30 21:04:27 353浏览 收藏

如果你在 Go Gonum 里看到 quad.Hermite{} 的示例,却疑惑为什么调用时必须给出负无穷到正无穷的区间,关键不在参数写法,而在这条规则已经把高斯型权函数写进了数学约定。Hermite 近似的是 ∫[-∞,+∞] e^(-x²) f(x) dx,其中 f(x) 是你传给 quad.Fixed 的剩余函数。

Hermite 不是普通的“全实数区间积分器”。它负责节点、权重和 e^(-x²) 权函数的组合;代码里只应传入权函数之外的部分,并把上下限写成 math.Inf(-1) 与 math.Inf(1)。

官方地址:https://pkg.go.dev/gonum.org/v1/gonum/integrate/quad

本文按一个常见排障现场展开:先确认 Hermite 到底计算什么,再给出可直接套用的 Go 写法,最后说明标准正态期望怎样做变量变换,以及结果不对时应该先查哪三项。

先把 Hermite 的“权”看成契约

Gonum 的 quad.Fixed 把固定节点求积抽象成“节点 xᵢ、权重 wᵢ 和函数值 f(xᵢ) 的加权和”。对于 Hermite 规则,官方文档把目标写成:

∫[-∞,+∞] e^(-x²) f(x) dx ≈ Σ wᵢ f(xᵢ)

因此权重并不是一组与区间无关的普通采样系数。它们是为平方指数权函数准备的,节点也分布在整个实数轴上。把它拿去理解有限区间上的无权积分,或者在 f 里再乘一次 e^(-x²),都会改变你实际近似的对象。

Hermite 求积入口、无限区间、节点权重与 e 负 x 平方权函数的静态关系说明图
图1:Hermite 求积契约的静态说明图,展示 API 入口、无限区间、节点权重和权函数之间的关系;这不是截图,也不是运行证据。

上下限为什么必须是负无穷和正无穷

Hermite.FixedLocations 会检查传入的边界:min 必须是负无穷,max 必须是正无穷。这个检查不是形式主义,它保证调用方使用的是 Hermite 规则对应的整个实数轴。如果写成 0 到 1,即使函数本身只在这段区间有意义,也不应继续使用 Hermite;应改用适合有限区间的规则,例如 quad.Legendre{}。

package main

import (
	"fmt"
	"math"

	"gonum.org/v1/gonum/integrate/quad"
)

func main() {
	// Hermite 只负责 e^(-x²) 之外的函数部分;这里计算 x² + 1。
	f := func(x float64) float64 {
		return x*x + 1
	}

	// Hermite 的区间契约是整个实数轴,样本数必须为正。
	value := quad.Fixed(f, math.Inf(-1), math.Inf(1), 16, quad.Hermite{}, 0)
	fmt.Printf("integral = %.8f\n", value)
}

这个调用对应的数学对象是 ∫e^(-x²)(x²+1)dx,而不是 ∫(x²+1)dx。最后一个参数是并发评估数;传入 0 表示串行计算,适合先把求积语义讲清楚。

函数里不要再次乘一遍权函数

最容易出现的误差是把“目标积分的完整被积函数”直接交给 Hermite。假设目标本来就是 ∫e^(-x²)q(x)dx,正确写法是传 q。如果把 e^(-x²)q(x) 作为 f,Hermite 的权重还会再贡献一次指数因子,实际求到的是 ∫e^(-2x²)q(x)dx。

// 正确:把权函数之外的 q(x) 交给 Hermite。
q := func(x float64) float64 {
	return x*x + 2
}
value := quad.Fixed(q, math.Inf(-1), math.Inf(1), 32, quad.Hermite{}, 0)

// 错误示意:这会把 e^(-x²) 乘进 Hermite 已经约定的权重,导致权函数重复。
wrong := func(x float64) float64 {
	return math.Exp(-x*x) * q(x)
}
_ = value
_ = wrong

这里的判断可以记成一句话:先把目标积分写成 e^(-x²) × 剩余函数,再把“剩余函数”作为 Go 闭包传入。不要因为示例中的闭包叫 f,就把完整被积函数机械地塞进去。

标准正态期望要先做一次变量变换

Hermite 的权函数是 e^(-x²),标准正态密度却是 1/√(2π)e^(-z²/2)。令 z=√2x,就得到:

E[g(Z)] = 1/√π ∫[-∞,+∞] e^(-x²) g(√2x) dx

所以 Go 代码里应当把 g 改写成 g(√2x),调用 Hermite 后再除以 √π。这个缩放因子属于变量变换,不属于 Hermite 权重本身。

标准正态密度经过 z 等于根号二乘 x 变换后连接 Hermite 求积的静态关系说明图
图2:标准正态期望的变量、缩放因子和 Hermite API 静态关系;这是解释图,不是截图,也不表示本机运行输出。
package main

import (
	"fmt"
	"math"

	"gonum.org/v1/gonum/integrate/quad"
)

func main() {
	// g 描述标准正态变量 Z 上真正关心的函数。
	g := func(z float64) float64 {
		return z*z + 2
	}

	// 变量变换 z = sqrt(2) * x,把 g 放到 Hermite 的剩余函数位置。
	transformed := func(x float64) float64 {
		return g(math.Sqrt2 * x)
	}

	// Hermite 先给出带 e^(-x²) 权的积分,再除以 sqrt(pi) 得到期望。
	integral := quad.Fixed(transformed, math.Inf(-1), math.Inf(1), 32, quad.Hermite{}, 0)
	expectation := integral / math.Sqrt(math.Pi)
	fmt.Printf("E[g(Z)] = %.8f\n", expectation)
}

结果不符合预期时先看这张表

现象优先检查对应判断
调用直接 panic上下限是否为 -Inf、+Inf,样本数是否大于 0Hermite 的区间和样本数契约未满足
结果比预期小很多是否在闭包里重复乘了 e^(-x²)权函数可能被重复计算
标准正态期望整体偏一个常数比例是否做了 z=√2x,并除以 √π变量变换的缩放因子遗漏
样本数增加后仍不稳定函数是否在节点附近平滑、是否真的适合全实数区间规则选择或被积函数形态可能不匹配

样本数 n 只改变 Hermite 节点和权重的数量,并不会把规则变成有限区间积分器。对于边界有限、没有平方指数权函数的目标,先重新选择规则,再谈增加采样点。

最后的判断方式

遇到“为什么 Hermite 求积包含权函数”的疑问,可以按三层判断:第一层看目标积分能否写成 e^(-x²)f(x);第二层看区间是否确实是整个实数轴;第三层看是否把变量变换的常数因子留在了 Hermite 调用之外。三层都匹配时,quad.Fixed 的调用就只是在执行 Gonum 文档定义的节点加权和。

Hermite 可以直接算有限区间吗?

不应这样用。Hermite 的实现要求边界为负无穷和正无穷;有限区间应选择与目标区间及权函数匹配的规则。

Hermite 权重是不是普通采样权重?

不是。它们和 e^(-x²) 的权函数约定绑定,用来近似带该权函数的全实数积分。

为什么正态期望还要除以平方根 pi?

因为 z=√2x 把标准正态密度转换成 1/√π · e^(-x²);除以 √π 是密度归一化后的常数因子。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>