新手陷阱 · 整数运算

为什么 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;,看看编译器怎么说。