新手陷阱 · 整数运算
为什么 C# 里 7 / 2 = 3?
这不是 bug 也不是四舍五入。当 / 两边都是整数时,C# 执行整数除法:算出 3.5 然后把小数扔掉。这里的每一段代码都能现场运行——自己验证。
Console.WriteLine(7 / 2); // int / int → int (3)
Console.WriteLine(7 / 2.0); // int / double → double
Console.WriteLine(7.0 / 2); // double / int → double
规则:只要任意一边是 double,另一边就被提升,结果保留小数。如果两边都是整数(int、long、short……),结果是整数,小数部分被丢弃——永远向零截断,不是"四舍五入"。
藏在变量里的版本(真正咬人的那个)
字面量的情况很明显。bug 出现在 double 藏在变量的声明类型里:
int a = 7;
Console.WriteLine(a / 2); // a 是 int → 整数除法 → 3
double x = 7; // 同样的值,不同的类型
Console.WriteLine(x / 2); // 现在 double / int → 3.5
这就是"我的测试里用 7 / 2.0 明明没问题,换上用户输入就错了"的由来:Console.ReadLine() 给你的是 string,而你一旦 int.Parse 它,下游的一切都进了整数运算。
是截断不是四舍五入——负数向零
Console.WriteLine(7 / 2); // 3.5 → 3 (小数直接丢弃)
Console.WriteLine(-7 / 2); // -3.5 → -3 (向零,不是向 -4!)
Console.WriteLine(9 / 2); // 4.5 → 4
Console.WriteLine(-9 / 2); // -4.5 → -4
C# 向零截断。如果你真想四舍五入,明确说出来:
Console.WriteLine(Math.Round(7 / 2.0)); // 3.5 → 4 (银行家舍入)
Console.WriteLine((int)Math.Ceiling(7 / 2.0)); // 永远向上 → 4
三种修法
修法一:把一边变成 double(最地道)
int a = 7, b = 2;
double result = a / (double)b;
Console.WriteLine(result);
一边转就够了——提升会传遍整个表达式。a / (double)b 和 (double)a / b 都行。
修法二:乘个 1.0(快糙猛)
int a = 7, b = 2;
Console.WriteLine(1.0 * a / b); // 1.0 * a 是 double → 全部提升
修法三:变量一开始就声明成 double
如果这些值本来就该有小数(价格、平均值、测量值),它们大概应该是 double:
double a = 7, b = 2;
Console.WriteLine(a / b);
关联陷阱:% 的符号跟着被除数走
取余运算符遵循同一套整数规则,而且结果符号跟随被除数:
Console.WriteLine(7 % 3); // 1
Console.WriteLine(-7 % 3); // -1 (符号跟 -7)
Console.WriteLine(7 % -3); // 1 (符号跟 7)
什么时候整数除法恰好就是你想要的
它不是设计缺陷——它正是你分页、分桶、分组的方式:
int totalItems = 98;
int pageSize = 10;
int fullPages = totalItems / pageSize; // 9 整页
int lastPageItems = totalItems % pageSize; // 8 个零头
Console.WriteLine((fullPages + (lastPageItems > 0 ? 1 : 0)) + " pages total");
Console.WriteLine(pageSize);
相关阅读:把 double 赋给 int 时悄悄吃掉小数的那个转换,是错误 CS0029 / CS0266。去练习场试试 int x = 3.5;,看看编译器怎么说。