如何将长度为N (其中0 < N < 64
)的给定位集转换为signed int。例如,给定:
std::bitset<13> b("1111111101100");
我想取回值-20,而不是8172.
我的方法:
int t = (static_cast<int>(b.to_ullong()));
if(t > pow(2, 13)/2)
t -= pow(2, 13);
有没有更通用的方法来解决这个问题?
编辑:此外,bitset实际上是std::bitset<64>
,N可以是通过其他方式传递的运行时已知值。
答案 0 :(得分:1)
我们可以编写一个函数模板来为我们这样做:
c(1, 2, 1, 2)
c(1, 2, 1, 4)
c(1, 2, 3, 2)
c(1, 2, 3, 4)
答案 1 :(得分:0)
也许最好让编译器自己对其进行签名扩展:
struct S { int64_t x:N; } s;
int64_t result = s.x = b.to_ullong();
编译器可能会优化s
。
它必须是安全的,因为int64_t
(如果可用)需要是两个补码。
编辑:当扩展的实际位数仅为已知运行时间时,大多数便携式算法都带有掩码:
// Do this if bits above position N in b may be are not zero to clear those.
int64_t x = b.to_ullong() & ((1ULL << N) - 1);
// Otherwise just
int64_t x = b.to_ullong();
int64_t const mask = 1ULL << (N - 1);
int64_t result = (x ^ mask) - mask;
具有动态位计数的稍快但不太便携的方法是位移(当架构已经签名算术右移时有效):
int const shift = 64 - N;
int64_t result = ((int64_t)b.to_ullong() << shift) >> shift;