有多少种方法可以看出一个数字是否均匀,哪一个是最快最清晰的?

时间:2009-05-16 01:36:57

标签: algorithm math

给出任何数字,确定它的最佳方法是什么?你能想到多少种方法,最快的方式和最清晰的方式是什么?

20 个答案:

答案 0 :(得分:33)

bool isEven = ((number & 0x01) == 0)

问题是“任何数字”,所以人们可以丢弃浮动或以另一种方式处理它们,也许首先将它们扩展到一个整数值 - 注意溢出 - 即改变2.1到21(乘以10)并转换为int)然后测试。然而,可以合理地假设,通过提及“任何数字”,提出问题的人实际上是指整数值。

答案 1 :(得分:28)

bool isEven = number % 2 == 0;

答案 2 :(得分:10)

isEven(n) = ((-1) ^ n) == 1

其中^是您语言的取幂/幂函数。

我没有说它快速或清晰,但它具有新颖的价值。

答案 3 :(得分:10)

答案取决于申请的职位。如果您申请 Enterprise Architect 职位,则以下内容可能适用:

首先,您应该创建一个正确的面向服务的体系结构,因为奇怪的服务肯定不会是您企业中唯一可重用的组件。 SOA 由服务,接口和服务使用者组成。该服务是可以通过网络调用的功能。它公开了一个接口契约,通常在目录服务中注册。

然后,您可以创建简单对象访问协议(SOAP) HTTP Web服务以公开您的服务。

接下来,您应该阻止客户端直接调用您的Web服务。如果你允许这样做,那么你最终会得到一堆点对点的通信,这很难维护。客户端应通过企业服务总线(ESB)访问Web服务。

除了提供标准的可插拔架构外,总线上还可能出现 service orchestration 等其他组件。

通常,应避免编写定制的偶数/奇数服务。您应该写一个提案请求(RFP),并让几个供应商向您展示他们的偶数/奇数服务。供应商的产品应该能够插入 ESB ,并为您提供服务水平协议(SLA)。

答案 4 :(得分:5)

这在红宝石中更容易:

isEven = number.even?

答案 5 :(得分:4)

如果int是32位,那么你可以这样做:

bool is_even = ((number << 31) >> 31) == 0;

使用位移,你会将最右边的位移到最左边的位置然后再移回,从而使所有其他位为0。那么你剩下的数字是0或1.这个方法有点类似于“数字和1”方法,你再次将所有位都设为0,除了第一个。

另一种方法,与此类似:

bool is_even = (number << 31) == 0;

bool is_odd = (number << 31) < 0;

如果数字是偶数(最右边的位是0),那么将它移位31个位置将使整数为0.如果该位为1,即数字为奇数,则结果数字为负数(最左边第1位的每个整数都是负数,除非数字是无符号类型,它不起作用)。要修复签名/未签名的错误,您只需测试:

bool is_odd = (number << 31) != 0;

答案 6 :(得分:4)

是..最快的方法是检查1位,因为它是针对所有奇数设置的,并且是针对所有偶数设置的。

按位AND非常快。

答案 7 :(得分:4)

如果您的类型'a'是整数类型,那么我们可以定义

even :: Integral a => a -> Bool
even n =  n `rem` 2 == 0

根据Haskell Prelude。

答案 8 :(得分:4)

对于浮点数,当然在合理范围内。

modf(n/2.0, &intpart, &fracpart)
return fracpart == 0.0

使用其他一些随机数学函数:

return gcd(n,2) == 2

return lcm(n,2) == n

return cos(n*pi) == 1.0

答案 9 :(得分:3)

实际上我认为(n%2 == 0)就足够了,这很容易理解,大多数编译器也会把它转换成位操作。

我用gcc -O2标志编译了这个程序:

#include <stdio.h>

int main()
{
    volatile int x = 310;
    printf("%d\n", x % 2);
    return 0;
}

,生成的汇编代码为

main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $32, %esp
    movl    $310, 28(%esp)
    movl    28(%esp), %eax
    movl    $.LC0, (%esp)
    movl    %eax, %edx
    shrl    $31, %edx
    addl    %edx, %eax
    andl    $1, %eax
    subl    %edx, %eax
    movl    %eax, 4(%esp)
    call    printf
    xorl    %eax, %eax
    leave
    ret

我们可以看到%2操作已经转换为andl指令。

答案 10 :(得分:3)

与DeadHead的评论相似,但效率更高:

#include <limits.h>

bool isEven(int num)
{
    bool arr[UINT_MAX] = { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
                           0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
                           // ...and so on
    };
    return arr[num];
}

与数组索引一样快,可能比也可能不比按位计算快(因为我不想编写这个函数的完整版本,所以很难测试)。对于它的价值,上面的函数只有足够的数据才能找到最多442的数字,但是必须转到4294967295来处理我的系统。

答案 11 :(得分:2)

预订有限的堆栈空间。 ;)(这可能是尾调用的候选者吗?)

public static bool IsEven(int num) {
    if (num < 0)
        return !IsEven(-num - 1);

    if (num == 0)
        return true;

    return IsEven(-num);
}

答案 12 :(得分:2)

a%2。

  1. 很明显
  2. 每个体面的编译器都很快。
  3. 每个人都在喊“但是!但是!如果编译器没有对它进行优化会怎样”应该找到正常的编译器,关闭并读取有关过早优化的信息,再次读取,再次读取。

答案 13 :(得分:1)

假设您正在处理整数,以下内容将起作用:

if((testnumber&amp; -2)== testnumber)然后testnumber是偶数。

基本上,如果数字为偶数,则十六进制中的-2将为FFFE(对于16位),然后与-2进行对数将保持不变。 **汤姆**

答案 14 :(得分:1)

如果它是低电平检查最后一个(LSB)位是0还是1:)

0 =偶数 1 =奇数

否则,+1 @sipwiz:“bool isEven = number%2 == 0;”

答案 15 :(得分:0)

递归!

function is_even (n number) returns boolean is
  if n = 0 then
     return true
  elsif n = 1 then
     return false
  elsif n < 0 then
     return is_even(n * -1)
  else
     return is_even(n - 2)
  end if
end

答案 16 :(得分:0)

继续“有多少种方式......”的精神:

function is_even (n positive_integer) returns boolean is
  i := 0
  j := 0
  loop
    if n = i then
       return (j = 0)
    end if;
    i := i + 1
    j := 1 - j
  end loop
end

答案 17 :(得分:0)

对Chris Lutz的回应,数组查找明显慢于BITWISE_AND操作。在数组查找中,您正在进行内存查找,由于内存延迟,它总是比按位操作慢。这当然不会影响将所有可能的int值放入数组的问题,该数组的内存复杂度为O(2 ^ n),其中n是总线大小(8,16,32,64)。

奇数/偶数属性仅以整数定义。所以任何处理浮点的答案都是无效的。这个问题的抽象表示是Int - &gt; bool(使用Haskell表示法)。

答案 18 :(得分:0)

另一个无用的新奇解决方案:

if (2 * (n/2) == n)
    return true;
else
    return false;

仅使用整数,这取决于语言如何处理整数除法。

n / 2 == n / 2如果是偶数或n / 2-.5如果它是奇数。 所以2 *(n / 2)== n,如果它是偶数,或者n - 1,如果它是奇数。

答案 19 :(得分:0)

您可以使用整数除法并将其除以2并检查余数或使用模数运算符并将其修改为2并检查余数。 “最快”的方式取决于语言,编译器和其他因素,但我怀疑有很多平台存在显着差异。