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.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 权重本身。

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,样本数是否大于 0 | Hermite 的区间和样本数契约未满足 |
| 结果比预期小很多 | 是否在闭包里重复乘了 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²);除以 √π 是密度归一化后的常数因子。
-
502 收藏
-
502 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
434 收藏
-
348 收藏
-
414 收藏
-
266 收藏
-
188 收藏
-
334 收藏
-
415 收藏
-
284 收藏
-
222 收藏
-
460 收藏
-
173 收藏
-
457 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习