存储&从位字段检索带符号的值

时间:2017-01-28 15:14:59

标签: c++ sqlite bit-manipulation

我需要在SQLite中存储和检索带符号的64位整数列(BigInt)的有符号整数值。为简单起见,假设该字段占用了BigInt的第一个BitCount位。还假设我们想要将RowID =:RowID的记录中的位字段更改为:Val并注意该字段使用的位是FldBits =(1<<< BitCount) - 1.

如果它是无符号值,则存储和检索非常简单。

// Store
update BigIntTbl set BigInt = BigInt & ~FldBits | :Val
where RowID=:RowID; 

// Retrieve
select BigInt & FldBits
from BigIntTbl where RowID=:RowID;   

我假设(但我不确定)存储有符号值的最佳方法是:在存储之前将Val设置为负值的二进制补码位。我已经提出了以下公式,但无法帮助我,但我觉得自己很难为自己做事。

// Store
update BigIntTbl set BigInt = BigInt & ~FldBits |
(:Val + (:Val<0) * (1 << BitCount))
// above sets :Val to 2s complement bit pattern for -ve values and leaves +ve values unchanged

// Retreive
select (BigInt & FldBits) - 2 * (BigInt & (1 << (BitCount-1)))
from BigIntTbl where RowID=:RowID;

我确实考虑过只应用一个偏移量(即在存储时添加偏移量,在检索时减去偏移量)但是,由于我不会进入的原因,我希望零存储为零。为了清楚起见,假设BigInt中的符号位(位63)从未使用过。

问题:

  1. 我可以更换吗? (:Val + (:Val<0) * (1 << BitCount))(:Val & FldBits)

  2. 比...更简单 (BigInt & FldBits) - 2 * (BigInt & (1 << (BitCount-1))) 用于检索?

1 个答案:

答案 0 :(得分:0)

解决方案(我希望)

采用64位有符号整数BigInt的一般情况,并考虑从位LoBit(基于0)开始并占用BitCount位的有符号位字段。

FldBits = ((1 << BitCount) - 1) << LoBit;

您可以将任意数字Val存储在 - (1&lt;&lt;(BitCount - 1))和(1&lt;(BitCount - 1)) - 1与

之间
BigInt = BigInt & ~FldBits | (Val << LoBit & FldBits)

并使用

检索它
Val = (BigInt & FldBits) << (64 - BitCount - LoBit) >> (64 - BitCount);

一个简单的SQL示例

select (?1 & 31) << 59 >> 59;

对于?1,-16和15之间的任何值都将返回?1(与'select?1&amp; 31'进行比较)。

双向移位导致位字段的最高位在所有较高位中被复制。如果Val是+ ve数字,则意味着它用零填充。如果Val是-ve它用填充的那些导致64位整数包含Val的64位表示。