浮点数转整数的截断是向零取整,非四舍五入或向下取整;正数如2.9→2,负数如-2.9→-2;浮点精度误差(如0.1+0.2≠0.3)会导致截断结果异常,金融等场景需先round或用高精度库;超范围转换结果未定义。

浮点数转整数时的“截断”,不是四舍五入,也不是向下取整,而是向零取整:直接丢掉小数部分,符号不变。3.9 → 3,-3.9 → -3。这个看似简单的操作,却在金融计算、分页偏移、坐标转换等场景中频繁引发隐蔽误差。
截断 ≠ 四舍五入,也 ≠ 向下取整
很多人误以为(int)或intval()会“按常识进位”,其实它只做一件事:砍掉小数点后所有数字。
- 正数如 2.9、2.5、2.1,截断后全是 2
- 负数如 -2.1、-2.5、-2.9,截断后全是 -2(不是 -3)
- floor(-2.9) 才是 -3,ceil(2.1) 才是 3,round(2.5) 在多数语言中是 2 或 3,取决于舍入规则
浮点精度会让截断“悄悄出错”
0.1 + 0.2 在内存中实际是 0.30000000000000004,不是精确的 0.3。这种微小偏差在乘法后会被放大:
- (int)(19.99 * 100) 可能得 1998 而非 1999(因 19.99 * 100 ≈ 1998.9999999999998)
- PHP 中 intval("0.9999999999999999") 是 0,但 (int)"0.9999999999999999" 可能变成 1(因字符串先转 float,再被近似为 1.0)
- 这类误差在金额、计费、索引计算中不可接受,必须前置 round() 或用 BCMath/bcmul 等高精度工具
溢出与未定义行为常被忽略
截断不检查范围。一个超出 int 类型表示能力的浮点数,转换结果是未定义的:
- float 值为 1e10 转 int16 → 可能是随机值、0,甚至触发异常
- C/C++ 标准明确写明:“无法表示时,结果值是未定义的”
- 安全做法是先用范围判断(如 value >= INT_MIN && value
不同语言的共性与细节差异
主流语言(C/C++、Python、Java、PHP、JavaScript)默认都采用向零截断,但实现细节和辅助函数有别:
- Python 的 int() 和 C 的 (int) 行为一致;math.trunc() 显式表达该意图
- JavaScript 提供 Math.trunc(),而 parseInt("3.9") 会先字符串解析,遇到小数点就停,和 Number(x) | 0 不同
- PHP 的 intval() 对字符串输入按字符解析,(int) 则先转 float 再截断,二者在边界值上可能不一致
- 所有语言中,若需四舍五入,都应调用 round()、lround()、roundToInt 等专用函数,而非依赖强转

















