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

就近舍入模式下浮点数乘法为何输出无穷大?

浮点数乘法舍入导致无穷大的疑问

测试代码

#include <fenv.h>
#include <iostream>
using namespace std;

int main(){
    fesetround(FE_TONEAREST);
    double a = 0x1.efc7f0001p+376;
    double b = -0x1.0fdfdp+961;
    double c = a*b;
    cout << a << " "<< b << " " << c << endl;
}

输出结果

2.98077e+113 -2.06992e+289 -inf

问题描述

我无法理解为何c的值为无穷大。我的理解是,无论最小的非无穷大浮点数是多少,它都应该比负无穷大更接近a*b的实际值,因为最小的非无穷大浮点数是有限的,任何有限数都比负无穷大更接近另一个有限数。为什么这里输出无穷大?

测试环境为64位x86平台,汇编使用SSE指令,以-O0编译,在clang和gcc中均出现此现象。

若使用向零舍入模式,结果为最小有限浮点数,因此我认为问题与舍入方式相关。


问题解答

要解释这个现象,得从IEEE 754双精度浮点数的范围和舍入规则入手:

  1. 双精度浮点数的可表示范围
    双精度double的指数范围是-1023到+1023,对应的最大有限值约为±1.79769e+308(准确值是(2 - 2^-52) * 2^1023)。当数值的绝对值超过这个范围时,就会触发上溢。

计算你代码中a*b的指数:

  • a的指数是376,b的指数是961,两者相加得376+961=1337,远大于double的最大指数1023。实际乘积的绝对值约为2^1337,是最大有限值的2^(1337-1023)=2^314倍,完全超出了有限浮点数的可表示范围。
  1. 不同舍入模式的上溢处理规则
    IEEE 754标准对不同舍入模式的上溢处理有明确规定:
  • 向零舍入(FE_TOWARDZERO):会截断到绝对值不超过实际值的最大可表示有限数,也就是你看到的“最小有限浮点数”(负的最大有限值)。
  • 向最近舍入(FE_TONEAREST,默认模式):当实际结果的绝对值大于最大有限值时,会舍入到符号相同的无穷大。这是因为在浮点数的对数刻度体系中,无穷大是最接近这个超范围值的可表示“值”——实际乘积的绝对值比最大有限值大了几个数量级,从舍入规则的角度,无穷大是符合“最近”要求的结果。

你之前的误解在于用线性空间的“距离”判断接近程度,但浮点数的舍入是基于标准定义的规则,而非线性空间的绝对距离。当数值超出有限范围时,向最近舍入模式会优先选择无穷大作为结果。


内容的提问来源于stack exchange,提问作者Heygard Flisch

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 02:25:47