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

Go strconv.ParseFloat 遇到 NaN 和 Inf 怎么区分

来源:17golang原创

时间:2026-09-09 18:44:53 501浏览 收藏

处理配置文件、CSV 或接口字段时,strconv.ParseFloat 可能返回的不是普通数字,而是 NaN、正无穷或负无穷。它们都能落到 float64,但含义完全不同:NaN 表示结果不可定义,+Inf-Inf 仍然有方向。判断时要先看 err,再用 math.IsNaNmath.IsInf,不要把所有非有限值混成一个“异常数字”。

要点速览
  • NaN 不等于自身,不能用 v == v 或普通等号识别。
  • math.IsInf(v, 1) 只判断正无穷,math.IsInf(v, -1) 只判断负无穷。
  • 普通数字溢出时也可能得到 Inf,但同时带 strconv.ErrRange,必须先处理错误。

ParseFloat 的特殊值到底返回什么

官方 strconv 文档把特殊文本作为 ParseFloat 的合法输入:NaN 不区分大小写;InfInfinity 也不区分大小写,并允许带正负号。成功解析时,返回值位于第一个结果,errnil

输入返回值推荐判断
NaNnanNaNmath.IsNaN(v)
Inf+Infinity正无穷math.IsInf(v, 1)
-Inf-infinity负无穷math.IsInf(v, -1)

这里的“合法”只说明文本符合解析器规则,不代表它适合直接进入业务计算。例如统计平均值时,NaN 可能污染后续结果;边界计算中的无穷也需要由业务决定是保留、拒绝还是转换为状态。

Go strconv.ParseFloat 将 NaN、Inf 和 Infinity 映射为不同 float64 特殊值的静态关系图
图1:ParseFloat 的输入词、float64 特殊值与 math 判断函数之间的静态对应关系。

用 math.IsNaN 和 math.IsInf 分支判断

最稳妥的分类函数把解析失败与解析成功分开。解析失败时,返回值即使看起来像无穷,也不能跳过错误检查;只有 err == nil 后的 Inf 才是输入明确要求的特殊值。

package main

import (
    "errors"
    "fmt"
    "math"
    "strconv"
)

func classifyFloat(raw string) (string, error) {
    // 不主动 TrimSpace,保持 ParseFloat 对输入边界的原始判断。
    value, err := strconv.ParseFloat(raw, 64)
    if err != nil {
        var numErr *strconv.NumError
        // 先区分范围错误,避免把普通数字溢出误报成合法 Inf。
        if errors.As(err, &numErr) && errors.Is(numErr.Err, strconv.ErrRange) {
            return "range-error", err
        }
        return "syntax-error", err
    }

    // NaN 不能用等号比较,必须调用 math.IsNaN。
    if math.IsNaN(value) {
        return "nan", nil
    }
    // sign=1 与 sign=-1 分别锁定正、负无穷。
    if math.IsInf(value, 1) {
        return "+inf", nil
    }
    if math.IsInf(value, -1) {
        return "-inf", nil
    }
    return "finite", nil
}

func main() {
    // 原始文本可来自配置或消息,分类结果交给上层业务处理。
    for _, raw := range []string{"12.5", "NaN", "-Infinity", "1e10000"} {
        kind, err := classifyFloat(raw)
        fmt.Printf("%q => %s, err=%v\n", raw, kind, err)
    }
}

math.IsInf(value, 0) 可以一次判断正负无穷,但需要知道方向时,使用 1-1 更直观。分类函数还保留了原始错误,调用方可以记录 NumError.Num,而不必从展示文本反推输入。

把输入词和数值状态分开存

这类问题适合采用“解析层与业务层分离”的小模式:解析层只负责把文本转换成值和错误,业务层再决定 NaN 或 Inf 的策略。不要把 NaN 转成 0 来“让流程继续”,因为 0 是确定的数值,NaN 是未知或不可定义,两者会让后续统计产生不同结果。

在记录结构中可以同时保留 rawkind 和可选的 value。这样日志或重试场景还能看到原始词,计算模块则只接收已经分类的结果。若业务只接受有限数字,就在这一层拒绝 nan+inf-inf,而不是散落在每个调用点。

Go 浮点文本解析层、math.IsNaN 与 math.IsInf 判断层和业务状态层的边界关系图
图2:将原始文本、ParseFloat 错误、float64 特殊值和业务状态分成清晰边界,避免错误类型混用。

几个容易写错的判断

  • 不要写 value == math.NaN() IEEE 754 的 NaN 不等于任何值,包括它自己,直接调用 math.IsNaN
  • 不要只判断 math.IsInf 例如一个超出目标精度范围的普通数字可能返回 Inf 和 ErrRange,这不是输入里的合法 Infinity。
  • 不要默认忽略空格。 如果接口约定允许首尾空白,可以在调用 ParseFloat 前明确清洗;否则应保留严格输入,避免把数据问题隐藏起来。
  • 注意 bitSize 传 32 时函数仍返回 float64,但按 float32 精度解析;传 64 才按 float64 精度解析。

常见问题

NaN 和空字符串都是解析失败吗?

不是。空字符串通常返回语法错误;NaN 是 ParseFloat 认可的特殊值,成功时 err == nil,应使用 math.IsNaN 识别。

Infinity 和 Inf 在 Go 中有什么区别?

对 ParseFloat 来说,两者都表示无穷,且匹配时不区分大小写;结果仍应通过 math.IsInf 判断方向。

能不能把 NaN 当成 0 保存?

只有业务明确规定缺失值映射为 0 时才可以,而且应在分类后显式转换;解析层不应擅自改变 NaN 的语义。

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