【问题标题】:Maximum of three integers using bitwise operations? [duplicate]使用按位运算最多三个整数? [复制]
【发布时间】:2023-03-21 02:32:02
【问题描述】:

如何仅使用按位运算返回三个无符号整数的最大值,例如 !,~,|,&,^,+,>>,

编辑:

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

/** 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) {
}

【问题讨论】:

  • 因为您根本没有要显示的代码,这里有一些提示可以帮助您入门: 取 10 个介于 1 和 100 之间的整数。对它们进行排序 写下它们的二进制表示。看二进制数。也许你有一个想法。

标签: c bit-manipulation


【解决方案1】:

查看“bit-twiddling hacks”页面并研究如何实现最大值/最小值。

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

让我给你解释一下获得最大值的两个数字的情况:


-(a&lt;b) 可以返回 -1 或 0,然后您可以使用 11111111 11111111 11111111 11111111(整数补码中的 -1)或 00000000 00000000 00000000 00000000(整数 -0 == 0)。

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

  • 如果a &lt; b你需要返回b作为结果,所以

a ^ ((a ^ b) &amp; -(a &lt; b)) 必须等于a ^ a ^ b.. 事实上这是因为-(a&lt;b) 返回11111111 11111111 11111111 11111111,并且对无符号整数的11111111 11111111 11111111 11111111 进行按位与& 运算使数字保持不变。 . 因此a ^ a ^ b = b。这是最大值。

  • 如果a &gt; ba &lt; b 为假,因此(anything &amp; 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;
}

编辑:如果您不允许使用“

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 个字节(并非在所有平台上都如此),那会更好。

【讨论】:

  • 我认为你不能使用&lt;
  • 幸运的是,您允许使用{。那些学校作业能有多傻?
  • 虽然我很喜欢 bit twiddling hacks 页面,但上面的答案并不完全有效,因为如果允许 a&lt;b,那么可以将 max(a,b) 定义为 a+(b&gt;a)*(b-a),这是相当比上面的简单。我不认为a&lt;b 是按位计算的。
  • 我同意,如果不允许使用 '
  • @DavidKernin 您编辑的解决方案依赖于有符号右移的特定行为,这是实现定义的。您可能应该将其添加为警告。
【解决方案2】:

如果允许您使用-(您建议使用+),我建议使用以下(未经测试),我认为这比位旋转页面更有效,特别是如果第一个最大值作为宏,并且我们知道我们正在处理带符号的整数。

#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'd 到 8。

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

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

不过,David Kernin 的回答更为笼统。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多