使用按位运算最多三个整数?

时间:2014-02-16 21:04:41

标签: c bit-manipulation

如何仅使用按位操作返回最多三个无符号整数,例如!,〜,|,&,^,+,>>,<<。我不知道从哪里开始。任何帮助将不胜感激。

编辑:

我只被允许使用给定的合法操作,就是这样。

/** maxOfThree - Returns the maximum of three integers.
* NOTE: x, y, z are all in the range [0, TMax].
* Examples: maxOfThree(1, 2, 3) = 3
* Legal Ops: ! ~ & ^ | + << >>
* Max Ops: 25
int maxOfThree(int x, int y, int z) {
}

2 个答案:

答案 0 :(得分:5)

看看&#34; bit-twiddling hacks&#34;页面并研究如何实现最大/最小。

如果你能弄清楚两个数字的最大值是如何工作的,那么你可以概括三个数字的情况。

让我向您解释获得最大值的两位数字:


-(a<b)可以返回-1或0,然后你可以有11111111 11111111 11111111 11111111(对于int的两个补码中的-1)或00000000 00000000 00000000 00000000(-0 =对于int而言= 0​​。

记住a^b^b = aa^b^a = b(不管订单是什么,这是xor操作),你在第一种情况下就是这样:

  • 如果a < b你需要返回b作为结果,那么

a ^ ((a ^ b) & -(a < b))必须等于a ^ a ^ b ..实际上它是-(a<b)返回11111111 11111111 11111111 11111111,并且按位和&amp;在11111111 11111111 11111111 11111111上操作无符号整数会使数字保持不变...因此a ^ a ^ b = b。这是最大值。

  • 如果a > ba < b为假,那么(anything & 00000000 00000000 00000000 00000000)为0.因此您有a ^ 0,即a。最大。

最后,我们将解决方案推广为三个数字:

#include <stdio.h>

int getMax(unsigned int a, unsigned int b, unsigned int c) {
    int temp = a ^ ((a ^ b) & -(a < b)) ;
    int r = c ^ ((c ^ temp) & -(c < temp));
    return r;
}

int main(void) {
    unsigned int a = 3, b = 1, c = 9;

    printf("%d", getMax(a,b,c));
    return 0;
}

编辑:如果您不允许使用&#34;&lt;&#34;然后使用第二个版本

x - ((x - y) & ((x - y) >> (sizeof(int) * CHAR_BIT - 1)));

并记住以下摘录

  

请注意,1989 ANSI C规范没有指定结果   签名右移,所以这些都不便携。如果抛出异常   在溢出时,x和y的值应该是无符号或转换为   没有签名的减法,以避免不必要的投掷   例外,右移需要一个带符号的操作数来产生   所有一位都是负数,所以转为签名


编辑II:这应该适用于您发布的规范:

#include <stdio.h>

int getMax(int x, int y, int z) {
    int r  =  (x + ~((x+~y+1) & ((x+~y+1) >> 31))+1); // if possible use sizeof(int)*sizeof(char)+~0 instead of 31
    int r2 =  (z + ~((z+~r+1) & ((z+~r+1) >> 31))+1); // if possible use sizeof(int)*sizeof(char)+~0 instead of 31
    return  r2;
}

int main(void) {
    unsigned int a = 5, b = 7, c = 1;

    printf("%d", getMax(a,b,c));
    return 0;
}

请注意,如果你可以使用sizeof()而不是假设int是4个字节(在所有平台上都不是真的那样)会更好。

答案 1 :(得分:0)

如果你被允许使用-(你建议+),我建议以下(未经测试),我觉得比比特翻页更有效,特别是如果第一个最大值为一个宏,我们知道我们正在处理签名的整数。

#define MAX2(a,b) (a-((a-b) >> (sizeof(int) * CHAR_BIT - 1))*(b-a))
int
max3 (int x, int y, int z)
{
    return MAX2(MAX2(x, y), z);
}
在大多数平台上,

CHAR_BIT应为#define'到8。

这也依赖于负数右移的未定义行为。

如果您不允许使用-,请使用~并添加1。

但是David Kernin的答案更为笼统。