c++ - 仅使用位操作(无分支)将 16 位有符号值限制在 0 到 4095 之间

标签 c++ c optimization bit-manipulation

我想将 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/

相关文章:

optimization - 如果我在 Haskell/GHC 中使用未装箱类型(如 Int#),我应该注意哪些事项?

c++ - 尝试按值返回对象时出现无效指针错误

c++ - 为什么 std::sub_match<T> 公开继承自 std::pair<T, T>?

c++ - ‘-’ token 之前应有非限定 ID

iphone - NSSearchPathForDirectoriesInDomains 解释混淆

css - 如何优化 Less CSS?如何生成所有 less 文件的 1 个缩小版本?我也在使用 modifyVars

c++ - CPP中原始数据类型的构造函数初始化

无法在 C 中打印 "* "

c - 如何限制用户输入字符串的大小或动态分配内存

通过分组优化 Python 打包