您会使用 num%2 还是 num&1 来检查一个数字是否为偶数?

好吧,至少有两种低级方法可以确定给定数字是否为偶数:

Well, there are at least two low-level ways of determining whether a given number is even or not:

 1. if (num%2 == 0) { /* even */ } 
 2. if ((num&1) == 0) { /* even */ }

我认为第二种选择更加优雅和有意义,这是我经常使用的一种.但这不仅仅是品味问题.实际性能可能会有所不同:通常按位运算(例如这里的逻辑与)比 mod(或 div)运算效率更高.当然,你可能会争辩说有些编译器无论如何都可以优化它,我同意……但有些不会.

I consider the second option to be far more elegant and meaningful, and that's the one I usually use. But it is not only a matter of taste; The actual performance may vary: usually the bitwise operations (such as the logial-and here) are far more efficient than a mod (or div) operation. Of course, you may argue that some compilers will be able to optimize it anyway, and I agree...but some won't.

另一点是,对于经验不足的程序员来说,第二个可能有点难以理解.我会回答说,如果这些程序员花这么短的时间来理解这种陈述,它可能只会使每个人受益.

Another point is that the second one might be a little harder to comprehend for less experienced programmers. On that I'd answer that it will probably only benefit everybody if these programmers take that short time to understand statements of this kind.

你怎么看?

仅当 num 是无符号整数或带有二进制补码表示的负数时,给定的两个片段才是正确的.- 正如一些评论所说的那样.

The given two snippets are correct only if num is either an unsigned int, or a negative number with a two's complement representation. - As some comments righfuly state.

推荐答案

如果你要说有些编译器不会优化 %2,那么你也要注意有些编译器使用有符号整数的一个补码表示.在这种表示中,&1 给出了负数的错误答案.

If you're going to say that some compilers won't optimise %2, then you should also note that some compilers use a ones' complement representation for signed integers. In that representation, &1 gives the wrong answer for negative numbers.

那么你想要什么――在某些编译器"上运行缓慢的代码,或者在某些编译器"上出现错误的代码?不一定在每种情况下都有相同的编译器,但这两种编译器都极为罕见.

So what do you want - code which is slow on "some compilers", or code which is wrong on "some compilers"? Not necessarily the same compilers in each case, but both kinds are extremely rare.

当然,如果 num 是无符号类型,或者是 C99 定宽整数类型之一(int8_t 等,要求是 2 的补码)),那么这不是问题.在这种情况下,我认为 %2 更优雅、更有意义,而 &1 是一种 hack,有时可能需要提高性能.例如,我认为 CPython 没有进行这种优化,完全解释的语言也是如此(尽管解析开销可能会使两个机器指令之间的差异相形见绌).不过,如果遇到 C 或 C++ 编译器在可能的情况下没有这样做,我会感到有些惊讶,因为如果不是在此之前,它在发出指令时是不费吹灰之力的.

Of course if num is of an unsigned type, or one of the C99 fixed-width integer types (int8_t and so on, which are required to be 2's complement), then this isn't an issue. In that case, I consider %2 to be more elegant and meaningful, and &1 to be a hack that might conceivably be necessary sometimes for performance. I think for example that CPython doesn't do this optimisation, and the same will be true of fully interpreted languages (although then the parsing overhead likely dwarfs the difference between the two machine instructions). I'd be a bit surprised to come across a C or C++ compiler that didn't do it where possible, though, because it's a no-brainer at the point of emitting instructions if not before.

一般来说,我会说在 C++ 中,您完全受制于编译器的优化能力.标准容器和算法有 n 级间接,当编译器完成内联和优化时,大部分都会消失.一个像样的 C++ 编译器可以在早餐前处理常量值的算术运算,而一个不像样的 C++ 编译器无论你做什么都会产生垃圾代码.

In general, I would say that in C++ you are completely at the mercy of the compiler's ability to optimise. Standard containers and algorithms have n levels of indirection, most of which disappears when the compiler has finished inlining and optimising. A decent C++ compiler can handle arithmetic with constant values before breakfast, and a non-decent C++ compiler will produce rubbish code no matter what you do.

相关文章