判断一个数是偶数还是奇数的最快方法是什么?

发布于 2024-08-20 23:16:56 字数 28 浏览 8 评论 0原文

判断一个数是偶数还是奇数的最快方法是什么?

What is the fastest way to find if a number is even or odd?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

面如桃花 2024-08-27 23:16:56

众所周知,它

static inline int is_odd_A(int x) { return x & 1; }

is_odd_A 更高效,

static inline int is_odd_B(int x) { return x % 2; }

但是在优化器打开的情况下,is_odd_Bis_odd_A 没有什么不同吗?否 — 使用 gcc-4.2 -O2,我们得到(在 ARM 汇编中):

_is_odd_A:
    and r0, r0, #1
    bx  lr

_is_odd_B:
    mov r3, r0, lsr #31
    add r0, r0, r3
    and r0, r0, #1
    rsb r0, r3, r0
    bx  lr

我们看到 is_odd_Bis_odd_A 多需要 3 条指令,主要原因是因为

((-1) % 2) == -1
((-1) & 1) ==  1

但是,以下所有版本都会生成与is_odd_A相同的代码:

#include <stdbool.h>
static inline bool is_odd_D(int x) { return x % 2; }      // note the bool
static inline int  is_odd_E(int x) { return x % 2 != 0; } // note the !=

这是什么意思?优化器通常足够复杂,对于这些简单的东西,最清晰的代码足以保证最佳效率

It is pretty well known that

static inline int is_odd_A(int x) { return x & 1; }

is more efficient than

static inline int is_odd_B(int x) { return x % 2; }

But with the optimizer on, will is_odd_B be no different from is_odd_A? No — with gcc-4.2 -O2, we get, (in ARM assembly):

_is_odd_A:
    and r0, r0, #1
    bx  lr

_is_odd_B:
    mov r3, r0, lsr #31
    add r0, r0, r3
    and r0, r0, #1
    rsb r0, r3, r0
    bx  lr

We see that is_odd_B takes 3 more instructions than is_odd_A, the main reason is because

((-1) % 2) == -1
((-1) & 1) ==  1

However, all the following versions will generate the same code as is_odd_A:

#include <stdbool.h>
static inline bool is_odd_D(int x) { return x % 2; }      // note the bool
static inline int  is_odd_E(int x) { return x % 2 != 0; } // note the !=

What does this mean? The optimizer is usually sophisticated enough that, for these simple stuff, the clearest code is enough to guarantee best efficiency.

对岸观火 2024-08-27 23:16:56

通常的方法:

int number = ...;
if(number % 2) { odd }
else { even }

替代方案:

int number = ...;
if(number & 1) { odd }
else { even }

在 GCC 3.3.1 和 4.3.2 上进行测试,两者的速度大致相同(没有编译器优化),因为两者都会产生 指令(在 x86 上编译) -我知道使用 div 指令进行取模会慢很多,因此我根本没有测试它。

Usual way to do it:

int number = ...;
if(number % 2) { odd }
else { even }

Alternative:

int number = ...;
if(number & 1) { odd }
else { even }

Tested on GCC 3.3.1 and 4.3.2, both have about the same speed (without compiler optimization) as both result in the and instruction (compiled on x86) - I know that using the div instruction for modulo would be much slower, thus I didn't test it at all.

乙白 2024-08-27 23:16:56

如果 (x & 1) 为真,则为奇数,否则为偶数。

if (x & 1) is true then it's odd, otherwise it's even.

何其悲哀 2024-08-27 23:16:56
bool is_odd = number & 1;
bool is_odd = number & 1;
GRAY°灰色天空 2024-08-27 23:16:56
int i=5;
if ( i%2 == 0 )
{
   // Even
} else {
   // Odd
}
int i=5;
if ( i%2 == 0 )
{
   // Even
} else {
   // Odd
}
春庭雪 2024-08-27 23:16:56
int is_odd(int n)
{
   if (n == 0)
      return 0;
   else if (n == 1)
      return 1;
   else
      return !is_odd(n - 1);
}

哦等等,你说的是最快方式,而不是最有趣。我的错;)

当然,上述函数仅适用于正数。

int is_odd(int n)
{
   if (n == 0)
      return 0;
   else if (n == 1)
      return 1;
   else
      return !is_odd(n - 1);
}

Oh wait, you said fastest way, not funniest. My bad ;)

Above function only works for positive numbers of course.

苦行僧 2024-08-27 23:16:56

检查最后一位是否为 1。

int is_odd(int num) {
  return num & 1;
}

Check to see if the last bit is 1.

int is_odd(int num) {
  return num & 1;
}
冰雪之触 2024-08-27 23:16:56

你的问题没有完全具体化。无论如何,答案取决于您的编译器和机器的体系结构。例如,您使用的计算机是否使用补码或二进制补码有符号数字表示形式?

我编写的代码首先是正确的,其次是清晰的,第三是简洁的,最后是快速的。因此,我将这个例程编码如下:

/* returns 0 if odd, 1 if even */
/* can use bool in C99 */
int IsEven(int n) {
    return n % 2 == 0;
}

这个方法是正确的,它比测试 LSB 更清楚地表达了意图,它很简洁,不管你相信与否,它的速度非常快。当且仅当分析告诉我这种方法是我的应用程序中的瓶颈时,我才会考虑偏离它。

Your question is not completely specified. Regardless, the answer is dependent on your compiler and the architecture of your machine. For example, are you on a machine using one's complement or two's complement signed number representations?

I write my code to be correct first, clear second, concise third and fast last. Therefore, I would code this routine as follows:

/* returns 0 if odd, 1 if even */
/* can use bool in C99 */
int IsEven(int n) {
    return n % 2 == 0;
}

This method is correct, it more clearly expresses the intent than testing the LSB, it's concise and, believe it or not, it is blazing fast. If and only if profiling told me that this method were a bottleneck in my application would I consider deviating from it.

不即不离 2024-08-27 23:16:56

如果它是一个整数,可能只检查最低有效位。零将被视为偶数。

If it's an integer, probably by just checking the least significant bit. Zero would be counted as even though.

情释 2024-08-27 23:16:56

可移植方法是使用模运算符 %

if (x % 2 == 0) // number is even

如果您知道您只会在二进制补码架构上运行,那么您可以使用按位与:

if (x & 0x01 == 0) // number is even

相对于按位与,使用模运算符可能会导致代码变慢;但是,除非满足以下所有条件,否则我会坚持使用它:

  1. 您无法满足严格的性能要求;
  2. 您正在执行x % 2很多(比如在一个被执行数千次的紧密循环中);
  3. 分析表明 mod 运算符的使用是瓶颈;
  4. 分析还表明使用按位和可以缓解瓶颈并且使您能够满足性能要求。

The portable way is to use the modulus operator %:

if (x % 2 == 0) // number is even

If you know that you're only ever going to run on two's complement architectures, you can use a bitwise and:

if (x & 0x01 == 0) // number is even

Using the modulus operator can result in slower code relative to the bitwise and; however, I'd stick with it unless all of the following are true:

  1. You are failing to meet a hard performance requirement;
  2. You are executing x % 2 a lot (say in a tight loop that's being executed thousands of times);
  3. Profiling indicates that usage of the mod operator is the bottleneck;
  4. Profiling also indicates that using the bitwise-and relieves the bottleneck and allows you to meet the performance requirement.
海之角 2024-08-27 23:16:56

检查最低有效位:

if (number & 0x01) {
  // It's odd
} else {
  // It's even
}

Check the least significant bit:

if (number & 0x01) {
  // It's odd
} else {
  // It's even
}
若水般的淡然安静女子 2024-08-27 23:16:56

如果输入以 10 为基数,您不能只查看最后一位数字并检查它是偶数还是奇数吗?

{1, 3, 5, 7, 9} 为奇数

{0, 2, 4, 6, 8} 为偶数

其他信息: OP 指出一个数字是给定的,所以我在构建这个答案时遵循了这一点。这还要求数字以 10 为基数。根据以 10 为基数的偶数/奇数定义,该答案在数学上是正确的。根据用例,只需检查最后一位数字即可获得数学上一致的结果。

注意:如果您的输入已经是int,则只需检查其低位即可。这个答案仅对表示为数字序列的数字有用。您可以转换int->string来执行此操作,但这会比n % 2 == 0慢得多。

检查最后一位数字确实适用于任何偶数基数的数字字符串,而不仅仅是 10。对于低于 10 的基数,例如基数 8(八进制),9 和 8 不是可能的数字,但低位数字是奇数或偶数仍然判断是否是整数。

对于高于 10 的基数,会有额外的可能性,但无论如何您都不想搜索列表,只需使用正常的 i % 2 == 0i % 2 == 0检查作为整数的数字是奇数还是偶数code> 或 !=0 检查。

对于使用 'a' .. 'f' 表示数字值 10 到 15 的 ASCII 十六进制,ASCII 代码的低位表示奇数或偶数,因为 'a' == 0x61 (奇数)但代表 10 又名 0xa (偶数)。因此,您必须将十六进制数字转换为整数,或者对 ASCII 代码进行一些位修改,以根据其他位或条件翻转低位。

Can't you just look at the last digit and check if its even or odd if the input is in base 10?

{1, 3, 5, 7, 9} is odd

{0, 2, 4, 6, 8} is even

Additional info: The OP states that a number is a given, so I went with that when constructing this answer. This also requires the number to be in base 10. This answer is mathematically correct by definition of even/odd in base 10. Depending on the use case, you have a mathematically consistent result just by checking the last digit.

Note: If your input is already an int, just check the low bit of that. This answer is only useful for numbers represented as a sequence of digits. You could convert int->string to do this, but that would be much slower than n % 2 == 0.

Checking the last digit does work for a string of digits in any even base, not just 10. For bases lower than 10, like base 8 (octal), 9 and 8 aren't possible digits, but the low digit being odd or even still determines whether the whole number is.

For bases higher than 10, there will be extra possibilities, but you don't want to search a list anyway, just check if the digit as an integer is odd or even using the normal i % 2 == 0 or !=0 check.

For ASCII hex using 'a' .. 'f' to represent digits values 10 through 15, the low bit of ASCII code does not represent odd or even, because 'a' == 0x61 (odd) but represents 10 aka 0xa (even). So you'd have to convert the hex digit to an integer, or do some bit-hack on the ASCII code to flip the low bit according to some other bit or condition.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文