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

为何显式整数转换未按预期执行?浮点运算疑问

浮点数截断结果的疑问

已知浮点数存储的是最接近的二进制可表示值而非精确值,以下是测试代码及输出:

测试代码

// This is just an example.
float f1 = 17.96f, f3 = 17.98f;
double d2 = 17.96, d4 = 17.98;
printf("1. 17.96 = %f (as cents:%d)\n", f1, (int)(f1 * 100));
printf("2. 17.96 = %lf (as cents:%d)\n", d2, (int)(d2 * 100));
printf("3. 17.98 = %f (as cents:%d)\n", f3, (int)(f3 * 100));
printf("4. 17.98 = %lf (as cents:%d)\n", d4, (int)(d4 * 100));

初始输出

1. 17.96 = 17.959999 (as int:1795)
2. 17.96 = 17.960000 (as int:1796)
3. 17.98 = 17.980000 (as int:1798)
4. 17.98 = 17.980000 (as int:1798)

高精度输出(保留25位小数)

1. 17.96 = 17.9599990844726562500000000 (as int:1795)
2. 17.96 = 17.9600000000000008526512829 (as int:1796)
3. 17.98 = 17.9799995422363281250000000 (as int:1798)
4. 17.98 = 17.9800000000000004263256415 (as int:1798)

核心疑问

根据f1的存储值17.95999908447265625,(int)(f1 * 100)得到1795符合整数截断规则;但f3的存储值是17.979999542236328125,乘以100后应为1797.9999542236328125,按截断规则应该得到1797,实际却得到1798,原因是什么?


问题解答

问题的核心是浮点数运算的精度范围与舍入规则:

当计算f3 * 100时,f3是float类型,运算精度由执行计算时的类型决定:

  1. 明确f3的精确值:17.979999542236328125确实是float能表示的最接近17.98的数值。
  2. float精度下的乘法运算:
    该值乘以100得到1797.9999542236328125,但这个数无法被float精确表示——float仅有24位二进制有效位(含隐含最高位1),在1798附近,float的最小精度单位(ULP)约为0.000061035。
    1797.9999542236328125与1798的差值为0.000045776,小于ULP的一半,因此float会将运算结果舍入到最接近的可表示值:1798。
  3. 整数截断的结果:
    舍入后的float值(1798)转换为int时,自然得到1798。

如果强制将运算提升到double精度执行:

(int)((double)f3 * 100)

此时1797.9999542236328125可被double精确表示,整数截断后会得到1797,与你预期一致。

注:不同编译器的运算优化策略可能影响是否自动提升精度,但多数情况下,同类型浮点数运算会保持原精度,因此出现你看到的结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 16:15:08