Convert vector<bool> to binary - c++

I have a vector<bool> that contains 10 elements. How can I convert it to a binary type;
vector<bool> a={0,1,1,1,1,0,1,1,1,0}
I want to get binary values, something like this:
long long int x = convert2bin(s)
cout << "x = " << x << endl
x = 0b0111101110
Note: the size of vector will be change during run time, max size = 400.
0b is important, I want to use the gcc extension, or some literal type.

As I understood of comment
Yes it can even hold 400 values
And in question
0b is important
You need to have string, not int.
std::string convert2bin(const std::vector<bool>& v)
{
std::string out("0b");
out.reserve(v.size() + 2);
for (bool b : v)
{
out += b ? '1' : '0';
}
return i;
}

std::vector<bool> a = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 0 };
std::string s = "";
for (bool b : a)
{
s += std::to_string(b);
}
int result = std::stoi(s);

If you really want to do this, you start from the end. Although I support Marius Bancila and advise to use a bitset instead.
int mValue = 0
for(int i=a.size()-1, pos=0; i>=0; i--, pos++)
{
// Here we create the bitmask for this value
if(a[i] == 1)
{
mask = 1;
mask << pos;
myValue |= mask;
}
}

Your x is just an integer form from a, so can use std::accumulate like following
long long x = accumulate(a.begin(), a.end(), 0,
[](long long p, long long q)
{ return (p << 1) + q; }
);
For a 400 size, you need a std::string though

First of all the result of the conversion is not a literal. So you may not use prefix 0b applied to variable x.
Here is an example
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <numeric>
#include <vector>
#include <iterator>
#include <limits>
int main()
{
std::vector<bool> v = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 0 };
typedef std::vector<bool>::size_type size_type;
size_type n = std::min<size_type>( v.size(),
std::numeric_limits<long long>::digits + 1 );
long long x = std::accumulate( v.begin(), std::next( v.begin(), n ), 0ll,
[]( long long acc, int value )
{
return acc << 1 | value;
} );
for ( int i : v ) std::cout << i;
std::cout << std::endl;
std::cout << std::hex << x << std::endl;
return 0;
}
The output is
0111101110
1ee

vector<bool> is already a "binary" type.
Converting to an int is not possible for more bits than available in an int. However if you want to be able to print in that format, you can use a facet and attach it to the locale then imbue() before you print your vector<bool>. Ideally you will "store" the locale once.
I don't know the GNU extension for printing an int with 0b prefix but you can get your print facet to do that.
A simpler way is to create a "wrapper" for your vector<bool> and print that.
Although vector<bool> is always internally implemented as a "bitset" there is no public method to extract the raw data out nor necessarily a standard representation for it.
You can of course convert it to a different type by iterating through it, although I guess you may have been looking for something else?

If the number of bits is known in advance and by some reason you need to start from an std::array rather than from an std::bitset directly, consider this option (inspired by this book):
#include <sstream>
#include <iostream>
#include <bitset>
#include <array>
#include <iterator>
/**
* #brief Converts an array of bools to a bitset
* #tparam nBits the size of the array
* #param bits the array of bools
* #return a bitset with size nBits
* #see https://www.linuxtopia.org/online_books/programming_books/c++_practical_programming/c++_practical_programming_192.html
*/
template <size_t nBits>
std::bitset<nBits> BitsToBitset(const std::array<bool, nBits> bits)
{
std::ostringstream oss;
std::copy(std::begin(bits), std::end(bits), std::ostream_iterator<bool>(oss, ""));
return std::bitset<nBits>(oss.str());
}
int main()
{
std::array<bool, 10> a = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 0 };
unsigned long int x = BitsToBitset(a).to_ulong();
std::cout << x << std::endl;
return x;
}

Related

Select value randomly from groups of values of different types

I have arrays of types int, bool and float:
std::array<int, 3>myInts = {15, 3, 6};
std::array<bool, 2>myBools = {true, false};
std::array<float,5>myFloats = {0.1, 15.2, 100.6, 10.44, 5.5};
I would like to generate a random integer(I know how to do that) from 0 to the total number of elements (3 + 2 + 5) so the generated random Integer represents one of the values. Next based on that integer I would like to retrieve my value and do further calculations with it. The problem I am facing is that I don't want to use if else statements like these:
int randInt = RandIntGen(0, myInts.size() + myBools.size() + myFloats.size());//Generates a random Integer
if(randInt<myInts.size()){//if the random integer is less than the size of the integers array I can choose
// from the the integers array
int myValue = myInts[RandInt]
}
else if(randInt>=myInts.size() && randInt<myBools.size() + myInts.size()){//if the random integer
//is between the size o the integer's array and the size of the bool's array + the size of the integers array
//then I can choose from the bool's array
bool myValue = myBools(RandInt - myInts.size())
}
.
.
.
Then if for example randInt=2 then myValue=6 or if randInt=4 then myValue=false
However I would like that the selection algorithm was more straightforward something like:
int randInt = RandIntGen(0, myInts.size() + myBools.size() + myFloats.size());
allValues = {myInts, myBools, myFloats}
if(type_id(allValues[randInt]).name=="int")
int myValue = allValues[randInt] //(this value will be used for further calculations)
if(type_id(allValues[randInt]).name=="bool")
bool myValue = allValues[randInt] //(this value will be used for further calculations)
I've tried with a mix of templates, inheritance and linked lists however I cannot implement what I want. I think the solution should be really simple but at this time I cannot think of something else.
I am novice in C++ I've been learning already for 1 and half months, before I was doing stuff in python and everything was way easier but then I decided to try C++. I am not a experienced programmer I know some basic things and I am trying to learn new things, thanks for the help.
Most probably, you need to think how to satisfy your requirements in a simpler way, but it is possible to get literally what you want with C++17. If your compiler doesn't support C++17, you can use corresponding boost libraries. Here is the code:
#include <array>
#include <iostream>
#include <tuple>
#include <variant>
using Result = std::variant<int, bool, float>;
template<class T>
bool take_impl(int& i, const T& vec, Result& result)
{
if (i < static_cast<int>(std::size(vec)))
result = vec[i];
i -= std::size(vec);
return i < 0;
}
template<class T>
Result take(int i, const T& arrays)
{
if (i < 0)
throw std::runtime_error("i is too small");
Result res;
std::apply([&i, &res](const auto&... array) { return (take_impl(i, array, res) || ...); }, arrays);
if (i >= 0)
throw std::runtime_error("i is too large");
return res;
}
std::ostream& operator<<(std::ostream& s, const Result& v)
{
if (std::holds_alternative<int>(v))
std::cout << "int(" << std::get<int>(v);
else if (std::holds_alternative<bool>(v))
std::cout << "bool(" << std::get<bool>(v);
else
std::cout << "float(" << std::get<float>(v);
return std::cout << ')';
}
auto arrays = std::make_tuple(
std::array<int, 3>{15, 3, 6},
std::array<bool, 2>{true, false},
std::array<float,5>{0.1, 15.2, 100.6, 10.44, 5.5}
);
int main()
{
for (int i = 0; i < 10; ++i)
std::cout << take(i, arrays) << '\n';
}
If you are not required to keep separate arrays of different types, you can make one uniform array of std::variant<int, bool, float>. This will be significantly more efficient than using std::shared_ptr-s.

Adding elements to std::vector in a repeated way

I want to copy values from one vector to other one that will be stored in a specific order and the second vector will contain more elements than the first one.
For example:
vector<int> temp;
temp.push_back(2);
temp.push_back(0);
temp.push_back(1);
int size1 = temp.size();
int size2 = 4;
vector<int> temp2(size1 * size2);
And now I would like to fill temp2 like that: {2, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1}.
Is it possible to do this using only algorithms (e.g. fill)?
Yes, it is possible using std::generate_n algorithm:
int main() {
std::vector<int> base{1, 0, 2};
const int factor = 4;
std::vector<int> out{};
std::generate_n(std::back_inserter(out), base.size() * factor,
[&base, counter=0]() mutable {
return base[counter++ / factor];
});
for(const auto i : out) {
std::cout << i << ' ';
}
}
This code prints: 1 1 1 1 0 0 0 0 2 2 2 2
The key is the lambda used in std::generate_n. It operates on internal counter to know which values, based on base vector (and accessed depending on factor and counter values), to generate.
No, this is quite a specific use case, but you can trivially implement it yourself.
#include <vector>
#include <iostream>
std::vector<int> Elongate(const std::vector<int>& src, const size_t factor)
{
std::vector<int> result;
result.reserve(src.size() * factor);
for (const auto& el : src)
result.insert(result.end(), factor, el);
return result;
}
int main()
{
std::vector<int> temp{2, 0, 1};
std::vector<int> real = Elongate(temp, 4);
for (const auto& el : real)
std::cerr << el << ' ';
std::cerr << '\n';
}
(live demo)

Int from byte representation in vector c++

I have a vector<int> of length n which contains only 0 and 1's. For example we can have the following vector of length 10:
0 1 1 0 1 0 0 1 0 0
Now I use the number represented by that vector to access a location in an array with 2^n entries (so in this case an array of 2^10 = 1024). I'm not sure how I can obtain one integer from the byte representation stored in this vector<int>.
Simply run through the vector and collect powers of 2.
It depends on which end of the vector you want as most significant digit but e.g.
auto to_int( const vector<int>& digits )
-> int
{
int result = 0;
for( int const digit : digits )
{
result += 2*result + digit;
}
return result;
}
Or the other way,
auto to_int( const vector<int>& digits )
-> int
{
int result = 0;
for( int i = (int)digits.size(); i --> 0; )
{
result += 2*result + digits[i];
}
return result;
}
Disclaimer: code not reviewed by compiler.
use a std::bitset (http://en.cppreference.com/w/cpp/utility/bitset) which has a to_ulong() method
Something like this:
int integer=0;
int c=0;
for(int i : intVector){
integer+=i<<c;
c++;
}
return integer;
A simply way using a for loop:
size_t val{0};
for (const auto i : vec)
val = (val << 1) + i;
You can keep the std::vector and use std::bitset:
#include <iostream>
#include <vector>
#include <bitset>
#include <algorithm>
#include <climits>
template <typename IterType>
unsigned long getValue(IterType i1, IterType i2)
{
unsigned long i = 0;
std::bitset<CHAR_BIT * sizeof(unsigned long)> b;
std::for_each(i1, i2, [&](auto n) { b.set(i++, n);});
return b.to_ulong();
}
int main()
{
std::vector<int> v = {0, 1, 1, 0, 1, 0, 0, 1, 0, 0};
auto val = getValue(v.rbegin(), v.rend());
std::cout << val << "\n";;
auto val2 = getValue(v.begin(), v.end());
std::cout << val2;
}
Note that depending on which bit is the most significant bit, you supply the iterators accordingly. For right-to-left, supply reverse iterators, otherwise supply forward iterators.
Live Example

Converting an array of 2 digit numbers into an integer (C++)

Is it possible to take an array filled with 2 digit numbers e.g.
[10,11,12,13,...]
and multiply each element in the list by 100^(position in the array) and sum the result so that:
mysteryFunction[10,11,12] //The function performs 10*100^0 + 11*100^1 + 12*100^3
= 121110
and also
mysteryFunction[10,11,12,13]
= 13121110
when I do not know the number of elements in the array?
(yes, the reverse of order is intended but not 100% necessary, and just in case you missed it the first time the numbers will always be 2 digits)
Just for a bit of background to the problem: this is to try to improve my attempt at an RSA encryption program, at the moment I am multiplying each member of the array by 100^(the position of the number) written out each time which means that each word which I use to encrypt must be a certain length.
For example to encrypt "ab" I have converted it to an array [10,11] but need to convert it to 1110 before I can put it through the RSA algorithm. I would need to adjust my code for if I then wanted to use a three letter word, again for a four letter word etc. which I'm sure you will agree is not ideal. My code is nothing like industry standard but I am happy to upload it should anyone want to see it (I have also already managed this in Haskell if anyone would like to see that). I thought that the background information was necessary just so that I don't get hundreds of downvotes from people thinking that I'm trying to trick them into doing homework for me. Thank you very much for any help, I really do appreciate it!
EDIT: Thank you for all of the answers! They perfectly answer the question that I asked but I am having problems incorporating them into my current program, if I post my code so far would you be able to help? When I tried to include the answer provided I got an error message (I can't vote up because I don't have enough reputation, sorry that I haven't accepted any answers yet).
#include <iostream>
#include <string>
#include <math.h>
int returnVal (char x)
{
return (int) x;
}
unsigned long long modExp(unsigned long long b, unsigned long long e, unsigned long long m)
{
unsigned long long remainder;
int x = 1;
while (e != 0)
{
remainder = e % 2;
e= e/2;
if (remainder == 1)
x = (x * b) % m;
b= (b * b) % m;
}
return x;
}
int main()
{
unsigned long long p = 80001;
unsigned long long q = 70021;
int e = 7;
unsigned long long n = p * q;
std::string foo = "ab";
for (int i = 0; i < foo.length(); i++);
{
std::cout << modExp (returnVal((foo[0]) - 87) + returnVal (foo[1] -87) * 100, e, n);
}
}
If you want to use plain C-style arrays, you will have to separately know the number of entries. With this approach, your mysterious function might be defined like this:
unsigned mysteryFunction(unsigned numbers[], size_t n)
{
unsigned result = 0;
unsigned factor = 1;
for (size_t i = 0; i < n; ++i)
{
result += factor * numbers[i];
factor *= 100;
}
return result;
}
You can test this code with the following:
#include <iostream>
int main()
{
unsigned ar[] = {10, 11, 12, 13};
std::cout << mysteryFunction(ar, 4) << "\n";
return 0;
}
On the other hand, if you want to utilize the STL's vector class, you won't separately need the size. The code itself won't need too many changes.
Also note that the built-in integer types cannot handle very large numbers, so you might want to look into an arbitrary precision number library, like GMP.
EDIT: Here's a version of the function which accepts a std::string and uses the characters' ASCII values minus 87 as the numbers:
unsigned mysteryFunction(const std::string& input)
{
unsigned result = 0;
unsigned factor = 1;
for (size_t i = 0; i < input.size(); ++i)
{
result += factor * (input[i] - 87);
factor *= 100;
}
return result;
}
The test code becomes:
#include <iostream>
#include <string>
int main()
{
std::string myString = "abcde";
std::cout << mysteryFunction(myString) << "\n";
return 0;
}
The program prints: 1413121110
As benedek mentioned, here's an implementation using dynamic arrays via std::vector.
unsigned mystery(std::vector<unsigned> vect)
{
unsigned result = 0;
unsigned factor = 1;
for (auto& item : vect)
{
result += factor * item;
factor *= 100;
}
return result;
}
void main(void)
{
std::vector<unsigned> ar;
ar.push_back(10);
ar.push_back(11);
ar.push_back(12);
ar.push_back(13);
std::cout << mystery(ar);
}
I would like to suggest the following solutions.
You could use standard algorithm std::accumulate declared in header <numeric>
For example
#include <iostream>
#include <numeric>
int main()
{
unsigned int a[] = { 10, 11, 12, 13 };
unsigned long long i = 1;
unsigned long long s =
std::accumulate( std::begin( a ), std::end( a ), 0ull,
[&]( unsigned long long acc, unsigned int x )
{
return ( acc += x * i, i *= 100, acc );
} );
std::cout << "s = " << s << std::endl;
return 0;
}
The output is
s = 13121110
The same can be done with using the range based for statement
#include <iostream>
#include <numeric>
int main()
{
unsigned int a[] = { 10, 11, 12, 13 };
unsigned long long i = 1;
unsigned long long s = 0;
for ( unsigned int x : a )
{
s += x * i; i *= 100;
}
std::cout << "s = " << s << std::endl;
return 0;
}
You could also write a separate function
unsigned long long mysteryFunction( const unsigned int a[], size_t n )
{
unsigned long long s = 0;
unsigned long long i = 1;
for ( size_t k = 0; k < n; k++ )
{
s += a[k] * i; i *= 100;
}
return s;
}
Also think about using std::string instead of integral numbers to keep an encrypted result.

Converting integer to a bit representation

How can I convert a integer to its bit representation. I want to take an integer and return a vector that has contains 1's and 0's of the integer's bit representation.
I'm having a heck of a time trying to do this myself so I thought I would ask to see if there was a built in library function that could help.
Doesn't work with negatives.
vector<int> convert(int x) {
vector<int> ret;
while(x) {
if (x&1)
ret.push_back(1);
else
ret.push_back(0);
x>>=1;
}
reverse(ret.begin(),ret.end());
return ret;
}
It's not too hard to solve with a one-liner, but there is actually a standard-library solution.
#include <bitset>
#include <algorithm>
std::vector< int > get_bits( unsigned long x ) {
std::string chars( std::bitset< sizeof(long) * CHAR_BIT >( x )
.to_string< char, std::char_traits<char>, std::allocator<char> >() );
std::transform( chars.begin(), chars.end(),
std::bind2nd( std::minus<char>(), '0' ) );
return std::vector< int >( chars.begin(), chars.end() );
}
C++0x even makes it easier!
#include <bitset>
std::vector< int > get_bits( unsigned long x ) {
std::string chars( std::bitset< sizeof(long) * CHAR_BIT >( x )
.to_string( char(0), char(1) ) );
return std::vector< int >( chars.begin(), chars.end() );
}
This is one of the more bizarre corners of the library. Perhaps really what they were driving at was serialization.
cout << bitset< 8 >( x ) << endl; // print 8 low-order bits of x
A modification of DCP's answer. The behavior is implementation defined for negative values of t. It provides all bits, even the leading zeros. Standard caveats related to the use of std::vector<bool> and it not being a proper container.
#include <vector> //for std::vector
#include <algorithm> //for std::reverse
#include <climits> //for CHAR_BIT
template<typename T>
std::vector<bool> convert(T t) {
std::vector<bool> ret;
for(unsigned int i = 0; i < sizeof(T) * CHAR_BIT; ++i, t >>= 1)
ret.push_back(t & 1);
std::reverse(ret.begin(), ret.end());
return ret;
}
And a version that [might] work with floating point values as well. And possibly other POD types. I haven't really tested this at all. It might work better for negative values, or it might work worse. I haven't put much thought into it.
template<typename T>
std::vector<bool> convert(T t) {
union {
T obj;
unsigned char bytes[sizeof(T)];
} uT;
uT.obj = t;
std::vector<bool> ret;
for(int i = sizeof(T)-1; i >= 0; --i)
for(unsigned int j = 0; j < CHAR_BIT; ++j, uT.bytes[i] >>= 1)
ret.push_back(uT.bytes[i] & 1);
std::reverse(ret.begin(), ret.end());
return ret;
}
Here is a version that works with negative numbers:
string get_bits(unsigned int x)
{
string ret;
for (unsigned int mask=0x80000000; mask; mask>>=1) {
ret += (x & mask) ? "1" : "0";
}
return ret;
}
The string can, of course, be replaced by a vector or indexed for bit values.
Returns a string instead of a vector, but can be easily changed.
template<typename T>
std::string get_bits(T value) {
int size = sizeof(value) * CHAR_BIT;
std::string ret;
ret.reserve(size);
for (int i = size-1; i >= 0; --i)
ret += (value & (1 << i)) == 0 ? '0' : '1';
return ret;
}
The world's worst integer to bit as bytes converter:
#include <algorithm>
#include <functional>
#include <iterator>
#include <stdlib.h>
class zero_ascii_iterator: public std::iterator<std::input_iterator_tag, char>
{
public:
zero_ascii_iterator &operator++()
{
return *this;
}
char operator *() const
{
return '0';
}
};
char bits[33];
_itoa(value, bits, 2);
std::transform(
bits,
bits + strlen(bits),
zero_ascii_iterator(),
bits,
std::minus<char>());