Bit hack根据第二个值返回两个值中的一个
Bit hack to return one of two values depending on the value of the second
假设x
是位掩码(即除一位外,其所有位都为0),y
是位掩码或等于0。如果y
为非零,我需要一个比特破解来返回x
,如果y
为零,则返回零。
这里有一个可能的解决方案:取x
和y
的以2为底的对数(使用德布鲁因序列)并将其相减,将值存储在d
中。则y << d
将返回x
,除非y
一开始为零。
这种方法有两个问题:1)如果y
为零,那么从技术上讲,以2为底的对数是未定义的。但不确定这是否重要,因为即使d
是某个垃圾值,如果y
为零,y << d
也应该返回零;2) 如果d
为负,则右移运算符不会变成左移运算符(根据谷歌搜索),这意味着我必须包括一些符号检查。
我相信有一种更简单的方法,但我找不到,希望能得到一些帮助。
编辑:为了澄清,我正在寻找最快的方法。显而易见的if (y == 0) return 0; else return x
使用了if
语句,因此受到分支预测的不利影响,这就是为什么我要使用复杂的base-2 log解决方案。
在大多数常见的处理器架构上,使用三元运算符是首选:
/* if y != 0, return x, else return 0 */
int select1 (int x, int y)
{
return y ? x : 0;
}
三元运算符的使用通常不涉及在现代处理器架构上使用分支,因为它可以通过使用条件移动(例如在x86上)、指令预测(例如在ARM上)或选择指令(例如在一些GPU上)以无分支的方式容易地实现。
如果不希望或不允许使用三元运算符,并且需要一个逐位的解决方案,则可以(假设平台对整数使用二的补码表示)使用:
/* if y != 0, return x, else return 0 */
int select2 (int x, int y)
{
return (0 - (y != 0)) & x;
}
注意,select2()
可能比select1()
慢。示例:如果我为x86-64体系结构编译上述函数,我的编译器将为select1()
生成此指令序列
test edx, edx
cmovne edx, ecx
mov eax, edx
ret
但是CCD_ 22:的这个较长的指令序列
mov r8d, 1
test edx, edx
cmovne edx, r8d
neg edx
and edx, ecx
mov eax, edx
ret
请注意,两个指令序列都不涉及作为值选择的一部分的分支,但与select1()
中的指令序列相比,select2()
中的指令顺序需要执行更多的指令,并且具有更长的依赖链。
static_cast<bool>(y) * x
只需取y,并使用其位形成一个所有1的字符串,如果它为非零,则将其与x进行and运算。实现这一点的愚蠢方法是线性的,但也可以使用二进制方法(未给出)。
#include <stdio.h>
#include <limits.h>
int foo(int x, int y) {
int z = 0;
for(int z = 1; z < CHAR_BIT * sizeof(int); z ++) {
y |= y << z;
}
return x & y;
}
int main() {
printf("%lxn", foo(0x1000, 0xdead));
return 0;
}
这应该在恒定的时间内运行。你当然可以展开这个循环。
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 如何返回一个类的两个对象相加的结果
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- C++需要帮助从用户那里获得一个整数,并确保它在另外两个整数之间
- 为什么C++在将一个对象复制到另一个对象时需要对这两个对象进行低级常量限定
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 我可以创建一个包含两个变量的 for 循环,但时间复杂度仍然为 O(n) 吗?
- 使用一个循环与两个循环
- 创建一个棋盘格或"Interweave"两个链接列表。IE 更改两个链表的指针
- 将向量之间的数字放在另一个向量之间<vector>>如果两个数字的差值为 1
- 如何巧妙地编写两个函数——一个用于检查是否存在解决方案,另一个用于获取所有解决方案
- 在Qt/C++中从一个代码构建两个略有不同的项目
- 我已经建立了递归关系,它找到了两个字符串之间最长的连续公共字符串,我怎么能跳过其中一个字符串中的一个字符
- 为什么在排序链表上的这种合并实现总是将两个列表都设置为 NULL,而只有一个应该设置一个列表?
- 如果两个静态库使用相同的另一个静态库,如何避免"LNK2005 Already Defined error"?
- 给定一个大小为 N 的数组 S,检查是否可以将序列拆分为两个序列
- 将两个 cpp 文件合并为一个 cpp 文件
- 为什么将两个浮点数相加会得到一个整数C++?
- 我如何创建一个列表,然后从中创建两个列表,其中一个用于偶数,另一个用于奇数?
- Makefile 创建两个库 - 一个依赖于另一个