You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Long.MaxValue转Single再转回Long触发OverflowException的原因探究

数值类型转换反常行为的原因解析

Long.MaxValue 的值为 9,223,372,036,854,775,807。将其转换为单精度(Single)值后变为 9.223372E18,但转换回 Long 时会抛出 System.OverflowException——尽管这个 Single 值看起来小于 Long 的最大值。

通过监视窗口实验发现:

  • 数值 8.070450532247929344e18 是可通过 CType 安全转换为 Long 的最大双精度(Double)值,可在监视窗口执行以下语句测试:
    CType(8.070450532247929344000001e18, Long)
    
  • 数值 8.070450807125836288e18 是先转换为 Single 后,可安全转换回 Long 的最大 Double 值,可在监视窗口执行以下语句测试:
    CType(CType(8.0704508071258362880000001e18, Single), Long)
    

上述反常行为的核心原因是浮点数的存储精度限制:

  1. Single 类型的精度瓶颈
    Single 是 32 位浮点数,仅含 23 位有效尾数(加隐含的 1 位共 24 位),仅能精确表示 2^24(即 16777216)以内的整数。超过该范围后,Single 无法精准表示每一个整数,而是以固定间隔的“阶梯值”近似存储。Long.MaxValue 转换为 Single 时会被近似为 9.223372E18,但该浮点值对应一个整数区间,转换回 Long 时区间上限会超过 Long.MaxValue,触发溢出异常。

  2. Double 转 Long 的精度边界
    Double 是 64 位浮点数,有 52 位有效尾数(加隐含位共 53 位),仅能精确表示 2^53(约 9e15)以内的整数。超过该范围后,相邻可表示的浮点值间隔大于 1,8.070450532247929344e18 是刚好小于 2^63(Long 最大值为 2^63-1)且能被 Double 精确表示的最大整数边界,超过它的话,Double 的间隔会跨越 Long.MaxValue,转换时就会溢出。

  3. Single 往返转换的额外精度损失
    Double 先转 Single 再转 Long 会经历两次精度损失:第一次是 Double 转 Single 时的近似,第二次是 Single 转 Long 时的区间判断。8.070450807125836288e18 是经过两次近似后仍能落在 Long 有效范围内的最大 Double 值,超过它的话,Single 近似后的区间会触及 Long 的上限。


补充实验

上述实验基于监视窗口和 CType,另一段实验代码得出了不同结果:

Dim d As Long = 200000000000
Dim delta As Long = d / 2
Dim c As Long
Dim a As Single
Dim b As Long
While delta > 0
    c = Long.MaxValue - d
    a = c
    Try
        b = a
        delta = delta \ 2

        d = d - delta
    Catch ex As Exception
        d = d + delta

    End Try
End While

该代码得出的可安全往返转换的最大 Long 值为:

9,223,371,761,976,868,860

即:

Long.MaxValue - 274,877,906,947

这个结果差异是因为代码采用二分法寻找可安全往返的最大 Long 值,直接针对「Long → Single → Long」的往返过程验证,而之前的监视窗口实验针对的是「Double → 目标类型」的单向/二次转换,测试场景不同,因此结果有区别。

内容的提问来源于stack exchange,提问作者J Collins

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 03:34:59