x % 2 == 0 是判断整数偶数最安全简洁的方法,天然支持负数、所有整型及 decimal(需写为 x % 2m == 0m),避免 math.abs 溢出和浮点精度问题;位运算 x & 1 == 0 更快但可读性差且不适用于浮点数。

用 % 判断偶数最直接,但要注意负数
在 C# 里,% 是取模运算符,不是“求余”,对负数行为和数学定义一致。比如 -4 % 2 结果是 0,所以它天然支持负数偶数判断,不用额外处理符号。
常见错误是误以为 % 在所有语言里都等价于“绝对值后取余”,其实 C# 的 % 遵循 IEEE 754 和 C# 规范:结果符号与被除数相同,但只要除数是 2,结果只可能是 0 或 1(或 -1,仅当被除数为负奇数时),而 == 0 这个判断对负偶数依然成立。
-
if (x % 2 == 0)是安全、简洁、可读性高的写法 - 避免用
Math.Abs(x) % 2 == 0——多一次函数调用,且对int.MinValue会溢出报错 - 如果
x是long或decimal,%同样适用,但decimal % 2要求右边也是decimal,即写成x % 2m == 0m
用位运算 & 更快,但只适用于整型且需理解原理
x & 1 == 0 是另一种主流做法,本质是检查二进制最低位是否为 0。它比 % 略快(尤其在循环密集场景),但代价是可读性下降,且不适用于浮点数或 decimal。
容易踩的坑是忽略类型隐式转换:如果 x 是 byte、short,& 操作会先提升为 int,结果仍是 int,所以比较时写 (x & 1) == 0 没问题;但若 x 是 uint 或 ulong,& 1 结果类型不变,仍可直接比较。
- 只对
sbyte、byte、short、ushort、int、uint、long、ulong有效 -
float、double、decimal不支持&,硬写会编译失败 - 对负数同样成立:
-6 & 1是0,因为 -6 的补码最低位确实是 0
别用 Math.Floor(x / 2) * 2 == x 这类浮点思路
有人从 JavaScript 或 Python 习惯出发,想用除法+取整反推,这在 C# 里既低效又危险。整数除法本就截断,但一旦 x 是 double,/ 就变成浮点除法,Math.Floor 引入精度误差,还可能遇到 NaN 或无穷大。
典型错误现象:9999999999999999.0 / 2 在 double 下无法精确表示,再乘回去可能不等于原值;或者 double.PositiveInfinity 直接让整个表达式崩掉。
- 整数场景下纯属绕远路,性能差一个数量级
- 浮点数本身没有“偶数”定义——偶数是整数概念,先用
Math.Round或Convert.ToInt64转整型再判断更合理 - 如果真要判断浮点数是否“接近某个偶数”,应明确容差,比如
Math.Abs(x - Math.Round(x / 2) * 2)
泛型方法封装时,注意 T 必须支持 % 或 &
C# 没有运算符约束,所以不能直接写 where T : %。想写通用判断,实际只能靠重载或运行时检查。最稳妥的是针对常用数值类型显式重载:
public static bool IsEven(int x) => x % 2 == 0; public static bool IsEven(long x) => x % 2 == 0; public static bool IsEven(uint x) => (x & 1) == 0;
试图用 dynamic 或反射做通用版,性能损失大,且对 decimal 仍得特殊处理(因为 decimal % decimal 是唯一支持取模的非整型)。
- 别用
Convert.ToDouble(x) % 2 == 0——转double可能丢精度,比如大整数 -
decimal必须用% 2m,写成% 2会触发隐式转换失败 - 自定义数值类型(如大数库)若没重载
%,就得提供专门的IsEven()方法
负数、类型边界、浮点歧义——这三个地方最容易被当成“理所当然”跳过去,结果在生产环境里埋下隐性 bug。










