我想将 signed short
变量的值限制在 0 到 4095 之间,之后我将最高有效的 8 位作为最终值用于其他地方。现在我正在以如下基本方式进行操作:
short color = /* some external source */;
/*
* I get the color value as a 16 bit signed integer from an
* external source I cannot trust. 16 bits are being used here
* for higher precision.
*/
if ( color < 0 ) {
color = 0;
}
else if ( color > 4095 ) {
color = 4095;
}
unsigned char color8bit = 0xFF & (color >> 4);
/*
* color8bit is my final value which I would actually use
* in my application.
*/
有什么方法可以仅使用位操作来完成,即不使用任何条件吗?它可能有助于加快速度,因为此操作在代码中发生了数千次。
以下内容无济于事,因为它不处理负值和溢出等边缘情况:
unsigned char color8bit = 0xFF & (( 0x0FFF & color ) >> 4 );
编辑: Adam Rosenfield's answer是采用正确方法但未正确实现的方法。 ouah's answer给出了正确的结果,但采用了与我最初打算找出的方法不同的方法。
这是我最终使用的:
const static short min = 0;
const static short max = 4095;
color = min ^ (( min ^ color ) & -( min < color ));
color = max ^ (( color ^ max ) & -( color < max ));
unsigned char color8bit = 0xFF & (( 0x0FFF & color ) >> 4 );
最佳答案
是的,参见 these bit-twiddling hacks :
short color = ...;
color = color ^ (color & -(color < 0)); // color = max(color, 0)
color = 4096 ^ ((color ^ 4096) & -(color < 4096)); // color = min(color, 4096)
unsigned char color8bit = 0xFF & (color >> 4);
我不知道这是否真的会更快,您应该分析一下。如今,大多数现代 x86 和 x86-64 芯片都支持“条件移动”指令 (cmov),这些指令根据 EFLAGS 状态位有条件地存储一个值,优化编译器通常会根据 color >= 0 这样的三元表达式生成这些指令?颜色:0
。这些可能是最快的,但它们无法在较旧的 x86 芯片上运行。
关于c++ - 仅使用位操作(无分支)将 16 位有符号值限制在 0 到 4095 之间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12308826/