Reputation: 38919
Let's hypothetically say that I have a collection of bits that I want to convert into an int
, but the bits may represent a negative 2's complement number, so for example:
vector<bool> foo = { true, false, false, false, false, true, false, false }
Obviously if foo.front()
is set then the number is negative. What would be the best way to convert this to an int
?
This question seems to lack clarity. For reference I've added my brute force solution here: https://stackoverflow.com/a/50108264/2642059 I want to accomplish this same thing but ideally with some provided functionality and not so much hackery.
Upvotes: 0
Views: 374
Reputation: 4191
std::vector<bool> foo;
//...
long long val=0;
for(auto& bit:foo){
val<<=1;
val+=bit;
};
if(foo.front())//sign extension
val+=~0ll<<foo.size();
Upvotes: 1
Reputation: 38919
The leading set bits for a number, including the bit that should be set for foo.front()
, can be generated by doing: -(1 << size(foo) - 1)
. After this you need only shift in the remainder of your bits.
This for example will generate the correct number whether or not foo.front()
is set:
int i = size(foo) - 1;
const auto bar = accumulate(next(cbegin(foo)), cend(foo), foo.front() ? -(1 << i) : 0, [&](const auto val, const auto it) { return val + (it << --i); });
Upvotes: 0
Reputation: 780724
In two's complement notation, the negative of a number is the complement plus 1.
When foo.first() == true
, convert all the remaining elements to binary digits, then invert it and add 1. Then return the negative of this.
So in your example, the remaining elements correspond to the binary number 0000000
. Complement this to 1111111
, which is 127
. Add 1
and you get 128
, and then you return -128
. And indeed, the value -128
is represented as 10000000
in 8-bit two's complement.
The signed data type you use for this process needs to be at least 1 bit larger than the size of the vector, to avoid overflowing when you add 1 to "all bits set" value. So if your vector can be up to 32 elements (including the sign), you need to use int64_t
.
Upvotes: 0