整数除法截断是向零取整而非四舍五入,操作数全为整型时结果必为整型且小数部分永久丢失;混合浮点类型可触发隐式提升实现浮点运算;嵌入式中宜用定点数、调整顺序或查表规避精度问题。

整数除法的截断不是“四舍五入”,而是直接丢弃小数部分
当你写 5 / 2,结果是 2,不是 2.5;7 / 3 得到 2,不是 2.333...。这不是精度不够,而是语言层面的定义行为:只要操作数全是整数类型(int、long、short 等),编译器就执行整数除法,结果强制为整数,小数部分被无条件截断(truncation toward zero)。
这种截断一旦发生,信息就永久丢失。后续再乘回去也恢复不了,比如:int a = 5; int b = a / 2 * 2;,b 是 4,不是 5。
类型提升不能绕过整数除法,但能帮你提前触发浮点运算
整型提升(如 char → int)只在算术表达式中生效,它不会把 int / int 变成浮点除法。真正起作用的是“混合类型运算”规则:当一个操作数是浮点类型时,另一个整数会被隐式提升为相同浮点类型,整个运算升格为浮点运算。
- 错误写法:
int result = 3 * 5 / 2;—— 全是int,中间5 / 2先得2,再3 * 2 = 6 - 正确写法:
double result = 3.0 * 5 / 2;——3.0是double,迫使5和2都转为double,全程按浮点算,得7.5 - 更稳妥写法:
double result = (double)3 * 5 / 2;—— 显式转换更清晰,避免字面量类型歧义
Java/Kotlin/C++ 中的常见踩坑点
不同语言对字面量和常量表达式的处理略有差异,容易误判“哪里开始变浮点”:
-
22 / 7在 Java 或 Kotlin 中永远是3,哪怕你把它赋给double变量:double pie = 22 / 7;—— 因为右侧先算整数除法,再把3赋值过去 - C++ 里
constexpr double pie = 22.0 / 7;没问题,但constexpr double pie = 22 / 7;仍是3.0 - 宏或常量定义要小心:
#define RATIO 3/2展开后仍是整数除法,应写成3.0/2或(double)3/2
嵌入式或资源受限场景下的务实选择
不是所有地方都能用 double:MCU 上浮点运算慢、占 Flash、还可能触发软浮点库。这时要换思路:
- 用定点数:比如把百分比放大 100 倍,
int value = (raw * 150) / 100;—— 注意防溢出,必要时先右移或分步算 - 调整计算顺序:把乘法放前面,减少截断累积,
(a * 100) / b比a / b * 100更准(前提是不溢出) - 查表或预计算:若分母固定(如除以 360 计算角度),可预先存好
1000000 / 360这类缩放因子,用整数乘法代替除法
真正难的不是“怎么写对”,而是判断哪一步的截断会传导、放大、最终破坏控制逻辑——比如电机 PID 的积分项里一次 /10 截断,跑 1000 周期后偏差可能超限。这类地方必须从数据流起点就锁定类型。










