math.IsNaN仅适用于float64,判断float32需转为float64或用v!=v;NaN与Inf是IEEE 754中两类独立特殊值,需分别用math.IsNaN和math.IsInf检测;JSON默认拒绝NaN/Inf,需手动处理。

Go 中 math.IsNaN 只能判断 float64,别传 float32
传 float32 给 math.IsNaN 会隐式转成 float64,但 NaN 的位模式在两种类型里不等价——float32(NaN) 转成 float64 后可能不再是 NaN(取决于具体 bit 表示),导致误判。
- 正确做法:用
math.IsNaN(float64(x))判断float32变量x,或直接用math.Float32bits+ 位运算(更准但麻烦) - 更稳妥的通用写法:
math.IsNaN(float64(v)) || (v != v)—— 因为 NaN 是唯一不等于自身的浮点数 - 注意:
v != v对float32和float64都有效,且无类型转换风险,但某些极端优化场景下可能被编译器误删(极少见)
Inf 不是 NaN,math.IsNaN 对 +Inf 或 -Inf 永远返回 false
这是最常混淆的点。NaN(Not a Number)和 Inf(Infinity)在 IEEE 754 里是两类独立特殊值。math.IsNaN 只认 NaN,对无穷大完全无感。
- 判断正无穷:
math.IsInf(v, 1);负无穷:math.IsInf(v, -1);任一无穷:math.IsInf(v, 0) -
math.IsInf(v, 0)比v == math.Inf(1) || v == math.Inf(-1)更可靠,因为浮点比较可能受精度或符号零干扰 - 如果业务逻辑要排除所有异常值(NaN + Inf),得两个函数都调:!
math.IsNaN(v) && !math.IsInf(v, 0)
从 JSON 解析浮点数时,NaN 和 Inf 默认被拒绝
Go 标准库 encoding/json 默认禁止解析 "NaN"、"Infinity" 这类字面量,会直接报错 invalid character 'N' looking for beginning of value 或类似错误。
- 想支持它们,必须用
json.Decoder.UseNumber()+ 手动解析字符串,再调strconv.ParseFloat(它接受"NaN"、"Inf") - 或者用第三方库如
github.com/mailru/easyjson并开启AllowNan选项 - 注意:
json.Marshal默认把 NaN/Inf 输出为空值(null),不是字符串,这点容易让前端困惑
计算中意外产生 NaN/Inf 往往源于未检查的除零或溢出
比如 0.0 / 0.0 → NaN,1.0 / 0.0 → +Inf,math.Exp(1000) → +Inf。这些不会 panic,但会让后续计算“污染”整条链。
立即学习“go语言免费学习笔记(深入)”;
- 关键位置加防护:比如归一化向量前先检查模长是否为 0 或 Inf
- 用
math.IsNaN和math.IsInf做断言比靠panic更早暴露问题 - 性能上,这两个函数是纯位操作,开销可忽略;但频繁调用说明设计上该收敛异常源头,而不是到处补检查
真正难的不是怎么调用 math.IsNaN,而是想清楚你的数据流里哪些环节可能产出 NaN/Inf,以及下游是否真的能安全处理它们——很多 bug 其实发生在“以为被过滤了”的地方,其实漏了一种边界输入。










