如何使用移位运算符将字节舍入为0或255

Mic*_*rey 3 c# bit-manipulation rounding

为了在我的C#项目中重新映射位图图像中的像素,我想将RGB值四舍五入到255或者降到0;

每个值都是一个字节.

现在我正在做以下事情:

(byte)(Pixels[i] < 128 ? 0 : 255);
Run Code Online (Sandbox Code Playgroud)

我相信这可以通过快速方式实现,并且无需使用按位操作进行类型转换.我该怎么做呢?

Han*_*ant 7

   (byte)(Pixels[i] < 128 ? 0 : 255)
Run Code Online (Sandbox Code Playgroud)

是的,如果位图包含太多的随机数据,由于分支预测较差,这往往表现不佳.抖动不会为此类语句生成条件移动.

您可以使用技巧,右移保留符号位以保存有符号的整数值.这使得此代码有效:

   (byte)((sbyte)Pixels[i] >> 7)
Run Code Online (Sandbox Code Playgroud)

哪个生成没有分支的代码:

000000a7  movsx       eax,byte ptr [edx+eax+8]  ; Pixels[i], sign extended to 32-bits
000000ac  sar         eax,7                     ; >> operator
000000af  and         eax,0FFh                  ; (byte) cast
Run Code Online (Sandbox Code Playgroud)


Cod*_*aos 5

一些可能性:

  • (byte)((b << 24) >> 31);
  • (byte)((sbyte)b >> 31);
  • (uint)(int)(sbyte)b >> 24;

前两个技巧是将大数字映射到负值,然后使用带符号的右移将结果转换为-1或0,最后转换回字节.

最后一个在理论上甚至更好,因为它可以在movsx eax,... shr eax, 24没有屏蔽的情况下编译到最终.但我怀疑.NET JITter是否意识到这一点.

只应在未经检查的上下文中使用.