1

例如,假设我将三个 10 位有符号整数打包成一个 Java 整数。

我可以轻松提取 10 位:

int unpacked = packed & 0x3FF;
packed >>= 10;
etc ...

但现在我需要对最高位(右边的第 9 位)进行符号扩展。有没有一种快速的方法可以通过测试最高位和设置来做到这一点?

也许有一种更好的拆包方式,可以将标志留在原处。

4

2 回答 2

4
int signed = (packed << (32 - 10)) >> (32 - 10);

>>>无符号右移和有符号右移也是如此>>

(我仍然有“错误”,谢谢@rghome)

于 2019-02-13T16:53:53.887 回答
4

移位两次的另一种方法是翻转符号然后减去它:

int unpacked = packed & 0x3FF;
int extended = (unpacked ^ 0x200) - 0x200;

如果没有设置符号,翻转它会设置它并减去它会再次重置它。

如果设置了符号,翻转它会重置它,减去它会再次设置它,但也会一直借到顶部,一路设置所有位。

这有一些好处,

  • 该代码不依赖于目标整数类型的大小,如果unpacked和那么同样的事情会起作用extendedlong
  • XOR 和减法可能会便宜一些,例如在 Skylake 上,您每个周期可以执行 4 次这些基本操作,但只能进行 2 次轮班。延迟是一样的,只有当代码中可用的 ILP 很高时才重要。
  • 移位并不能真正以代数方式组合,但 XOR 和减法可以。例如,如果下一个操作是将某个常量添加到extended,那么可以将加法和“减号”步骤合并为一个操作。
于 2019-02-14T02:04:54.577 回答