There is a method to convert a std::vector<uint64> to a single number?
I have a vector like this:
v[0] = 0;
v[1] = 6796890219657246832;
Or like this:
v[0] = 16377;
v[1] = 2631694347470643681;
v[2] = 11730294873282192384;
The result I like to get is, in the first case 6796890219657246832 and in the second: 16377263169434747064368111730294873282192384. My main problem is choosing the data type for the value as it is possible that the vector size is not always 2 but it could be 5 or higher.
No C++ provided types will support that many digits. So obviously, you need BIG-INT for that. Ethier implemented by yourself or using a tested library like GMP.
For example, using GMP will be like:
static mpz_class convert_to_i(std::vector<std::size_t> const& vec)
{
std::string sum;
for (auto const number : vec) {
sum += std::to_string(number);
}
return mpz_class(sum);
}
Let the vec be:
std::vector<std::size_t> const vec = {
16377,
2631694347470643681,
1173029487328219238
};
Result of convert_to_i(vec) will be:
1637726316943474706436811173029487328219238
If your original numbers are also big-int:
static mpz_class convert_to_i(std::vector<mpz_class> const& vec)
{
std::string sum;
for (auto const& number : vec) {
sum += number.get_str();
}
return mpz_class(sum);
}
Let the vec_2 be:
std::vector<mpz_class> const vec_2 = {
mpz_class("26316943474706436812631694347470643681"),
mpz_class("263169434747064368126316943474706436812631694347470643681")
};
Result of convert_to_i(vec_2) will be:
26316943474706436812631694347470643681263169434747064368126316943474706436812631694347470643681
Just for copy/paste and test: the code.
The Boost.Multiprecision library can be used for computations with very large numbers. This will do what you want using that library:
#include <boost/multiprecision/cpp_int.hpp>
#include <vector>
#include <cstdint>
#include <iostream>
namespace mp = boost::multiprecision;
mp::cpp_int add_numbers(const std::vector<uint64_t> &numbers)
{
mp::cpp_int sum = 0;
size_t digits = 0;
for (std::vector<uint64_t>::const_reverse_iterator it = numbers.crbegin(); it != numbers.crend(); ++it)
{
mp::cpp_int num(*it);
sum += num * mp::pow(mp::cpp_int(10), digits);
digits += num.str().size();
}
return sum;
}
int main() {
std::vector<uint64_t> numbers = {16377U, 2631694347470643681U, 11730294873282192384U};
mp::cpp_int sum = add_numbers(numbers);
std::cout << sum << std::endl;
}
Output:
16377263169434747064368111730294873282192384
Live demo
use std::accumulate and generate a string.
std::string result = std::accumulate (
v.begin(),
v.end(),
std::string(),
[](const std::string &result, const uint64 &val) {
return result + std::to_string(val); }
);
Related
I have a vector of integers:
std::vector<int> values = {1,2,3,4,5,6,7,8,9,10};
Given that values.size() will always be even.
I simply want to convert the adjacent elements into a pair, like this:
std::vector<std::pair<int,int>> values = { {1,2}, {3,4} , {5,6}, {7,8} ,{9,10} };
I.e., the two adjacent elements are joined into a pair.
What STL algorithm can I use to easily achieve this? Is it possible to achieve this through some standard algorithms?
Of course, I can easily write an old school indexed for loop to achieve that. But I want to know what the simplest solution could look like using rangebased for loops or any other STL algorithm, like std::transform, etc.
Once we have C++23's extension to <ranges>, you can get most of the way there with std::ranges::views::chunk, although that produces subranges, not pairs.
#include <iostream>
#include <ranges>
#include <vector>
int main()
{
std::vector<int> values = {1,2,3,4,5,6,7,8,9,10};
auto chunk_to_pair = [](auto chunk)
{
return std::pair(*chunk.begin(), *std::next(chunk.begin()));
};
for (auto [first, second] : values | std::ranges::views::chunk(2) | std::ranges::views::transform(chunk_to_pair))
{
std::cout << first << second << std::endl;
}
}
Alternatively, you could achieve a similar result by ziping a pair of strided views
#include <iostream>
#include <ranges>
#include <vector>
int main()
{
std::vector<int> values = {1,2,3,4,5,6,7,8,9,10};
auto odds = values | std::ranges::views::drop(0) | std::ranges::views::stride(2);
auto evens = values | std::ranges::views::drop(1) | std::ranges::views::stride(2);
for (auto [first, second] : std::ranges::views::zip(odds, evens))
{
std::cout << first << second << std::endl;
}
}
That last one can be generalised to n-tuples
template <size_t N>
struct tuple_chunk_t
{
template <typename R, size_t... Is>
auto impl(R && r, std::index_sequence<Is...>)
{
using namespace ranges::view;
return zip(r | drop(Is) | stride(N)...);
}
template <typename R>
auto operator()(R && r) const
{
return impl(std::forward<R>(r), std::make_index_sequence<N>{});
}
template <typename R>
friend auto operator|(R && r, chunk_t)
{
return impl(std::forward<R>(r), std::make_index_sequence<N>{});
}
};
template <size_t N>
constexpr tuple_chunk_t<N> tuple_chunk;
I'm not sure why you would require a standard algorithm when writing it yourself is roughly 5 lines of code (plus boilerplate):
template<class T>
std::vector<std::pair<T, T>> group_pairs(const std::vector<T>& values)
{
assert(values.size() % 2 == 0);
auto output = std::vector<std::pair<T, T>>();
output.reserve(values.size()/2);
for(size_t i = 0; i < values.size(); i+=2)
output.emplace_back(values[i], values[i+1]);
return output;
}
And call it like so:
std::vector<int> values = {1,2,3,4,5,6,7,8,9,10};
auto result = group_pairs(values)
Live Demo
I am not aware of a standard algorithm that does what you want directly (though I am not very familiar with C++20 and beyond). You can always write a loop and most loops can be expressed via std::for_each which is a standard algorithm.
As you are accumulating elements in pairs, I would give std::accumulate a try:
#include <vector>
#include <numeric>
#include <iostream>
struct pair_accumulator {
std::vector<std::pair<int,int>> result;
int temp = 0;
bool set = false;
pair_accumulator& operator+(int x){
if (set) {
result.push_back({temp,x});
set = false;
} else {
temp = x;
set = true;
}
return *this;
}
};
int main() {
std::vector<int> values = {1,2,3,4,5,6,7,8,9,10};
auto x = std::accumulate(values.begin(),values.end(),pair_accumulator{}).result;
for (const auto& e : x) {
std::cout << e.first << " " << e.second << "\n";
}
}
Whether this is simpler than writing a plain loop is questionable admittedly.
If possible I would try to not transform the vector. Instead of accessing result[i].first you can as well use values[i*2] and similar for second. If this is not feasible the next option is to populate a std::vector<std::pair<int,int>> from the start so you don't have to do the transformation. For the first, depending on what you need in details, the following might be a start:
#include <vector>
#include <iostream>
struct view_as_pairs {
std::vector<int>& values;
struct proxy {
std::vector<int>::iterator it;
int& first() { return *it;}
int& second() { return *(it +1); }
};
proxy operator[](size_t index){
return proxy{values.begin() + index*2};
}
size_t size() { return values.size() / 2;}
};
int main() {
std::vector<int> values = {1,2,3,4,5,6,7,8,9,10};
view_as_pairs v{values};
for (size_t i=0; i < v.size(); ++i){
std::cout << v[i].first() << " " << v[i].second() << "\n";
}
}
TL;DR: Consider if you can avoid the transformation. If you cannot avoid it, it is probably cleanest to write a loop. Standard algorithms help often but not always.
OK, I hinted in the comments about using std::adjacent_find, so here is how you would do this.
And yes, many (even myself) considers this a hack, where we are using a tool meant for something else to make short work of solving a seemingly unrelated problem:
#include <algorithm>
#include <iostream>
#include <utility>
#include <vector>
int main()
{
//Test data
std::vector<int> v = {1,2,3,4,5,6,7,8,9,10};
// results
std::vector<std::pair<int,int>> result;
// save flag
bool save_it = true;
// Use std::adjacent_find
std::adjacent_find(v.begin(), v.end(), [&](int n1, int n2)
{ if (save_it) result.push_back({n1,n2}); save_it = !save_it; return false; });
for (auto& pr : result)
std::cout << pr.first << " " << pr.second << "\n";
}
Output:
1 2
3 4
5 6
7 8
9 10
The way it works is we ignore the second, fourth, sixth, etc. pairs, and only save the first, third, fifth, etc. pairs. That's controlled by a boolean flag variable, save_it.
Note that since we want to process all pairs, the std::adjacent_find predicate always returns false. That's the hackish part of this solution.
The solutions so far try to use the std::vector iterators as input to the algorithms directly. How about defining a custom iterator that returns a std::pair and has strides of 2? Creating the vector of pairs is then a one-liner that uses std::copy. The iterator effectively provides a "view" onto the original vector in terms of pairs. This also allows the use of many of the standard algorithms. The following example could also be generalized quite a bit to work with most container iterators, i.e. you do the difficult work of defining such an iterator once and then you can apply it to all sorts of containers and algorithms. Live example: https://godbolt.org/z/ceEsvKhzd
#include <vector>
#include <algorithm>
#include <iostream>
#include <cassert>
struct pair_iterator {
using difference_type = std::vector<int>::const_iterator::difference_type;
using value_type = std::pair<int, int>;
using pointer = value_type*;
using reference = value_type; // Not a pair&, but that is ok for LegacyIterator
// Can't be forward_iterator_tag because "reference" is not a pair&
using iterator_category = std::input_iterator_tag;
reference operator*()const { return {*base_iter, *(base_iter + 1)}; }
pair_iterator & operator++() { base_iter += 2; return *this; }
pair_iterator operator++(int) { auto ret = *this; ++(*this); return ret; }
friend bool operator==(pair_iterator lhs, pair_iterator rhs){
return lhs.base_iter == rhs.base_iter;
}
friend bool operator!=(pair_iterator lhs, pair_iterator rhs){
return lhs.base_iter != rhs.base_iter;
}
std::vector<int>::const_iterator base_iter{};
};
auto pair_begin(std::vector<int> const & v){ assert(v.size()%2==0); return pair_iterator{v.begin()}; }
auto pair_end(std::vector<int> const & v){ assert(v.size()%2==0); return pair_iterator{v.end()}; }
int main()
{
std::vector<int> values = {1,2,3,4,5,6,7,8,9,10};
std::vector<std::pair<int, int>> pair_values;
std::copy(pair_begin(values), pair_end(values), std::back_inserter(pair_values));
for (auto const & pair : pair_values) {
std::cout << "{" << pair.first << "," << pair.second << "} ";
}
std::cout << std::endl;
}
I want to take an integer and turn it into an array and then store it into a string in C++. But I do not know how to turn an integer into an array and then store it into a string. I am still learning C++, so help me, please. That's how I want it to be done:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int number = 3215;
//store the number into vector
vector<int> numbers;
//vector[0]=3
//vector[1]=2
//vector[2]=1
//vector[5]=5
//and then store it into string
string str;
//like this
//str=3215
return 0;
}
Please help me and show the code as well with explanation
Edit: I have some data to work with integer values with every digit which I can solve my own but for that, I need to first turn the integer into vector and return it as a string. THat's why I want to know how to turn integer into vector first and the that vector into string
Here you are:
#include <iostream>
#include <vector>
#include <cmath>
#include <string>
#include <algorithm>
#include <iterator>
int main() {
int n;
std::cin >> n;
std::vector<int> split(static_cast<int>(std::log10(n)) + 1);
auto royal_10 = split.rbegin();
auto cpy{ n };
do {
*royal_10++ = cpy % 10;
} while ((cpy /= 10) != 0);
std::string ret;
ret.reserve(split.size());
std::transform(split.cbegin(), split.cend(), std::back_inserter(ret),
[](int const dig) { return dig + '0'; });
return 0;
}
The easiest is : std::to_string(yourNum);
If you do need the steps:
std::vector<int> res;
int num;
std::cin >> num;
while(num>0)
{
res.insert(res.begin(),num%10);
num/=10;
}
and then
std::stringstream result;
std::copy(res.begin(), res.end(), std::ostream_iterator<int>(result, ""));
Since you insist on placing the integers in a vector first and then converting them to string later (when needed?), this can be a solution:
#include <iostream>
#include <string>
#include <vector>
int main( )
{
std::string number;
std::cin >> number;
std::vector<int> numbers;
numbers.reserve( number.length( ) );
for ( const auto digit : number )
{
numbers.push_back( digit - '0' );
}
std::cout << "\nElements of vector: ";
for ( const auto digit : numbers )
{
std::cout << digit << ' ';
}
std::cout << "\nElements of vector converted to `std::string`: ";
for ( const auto num : numbers )
{
std::string num_str { std::to_string( num ) };
std::cout << num_str << ' ';
}
std::cout << '\n';
}
Sample I/O:
1234
Elements of vector: 1 2 3 4
Elements of vector converted to `std::string`: 1 2 3 4
You are asking for a set of conversion functions, probably something like the code below. The ASCII codes of the digits are in sequential order, therefore transforming a digit character to a digit means subtracting '0' from it.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cassert>
std::vector<int> convert(const std::string& s)
{
std::vector<int> r;
std::transform(s.begin(), s.end(), std::back_inserter(r), [](auto e) {return e - '0'; });
return r;
}
std::string convert(const std::vector<int>& v)
{
std::string r;
std::transform(v.begin(), v.end(), std::back_inserter(r), [](auto e) {return e + '0'; });
return r;
}
std::vector<int> convert(const int n)
{
return convert(std::to_string(n));
}
int main()
{
auto v = convert(3215);
auto s = convert(v);
assert(s == "3215");
}
1)vector in c++ has vector object.push_back(); // which push data(any type) to vector array
2) using an iterator function you can retrieve that data and by dereferencing(*i)
you can receive that data in original form (which you had pushed)
3) use stringstream class or to_string() method to convert into string
//code
`
#include<vector>
#include<iostream>
int main()
{
int number=1234;
string str;
vector <int> obj;
obj.push_back(number);
for(auto i= obj.begin(); i!= obj.end();i++)
{
str = to_string((*i));
cout << end << str;
}
}
`
I need to update a 100M-element array and would like to do it in parallel. std::for_each(std::execution::par, ...) seems great for this, except that the update needs to access elements of other arrays depending on the index that I am updating. A minimal serial working example of the kind of thing I'm trying to parallelize might look like this:
for (size_t i = 0; i < 100'000'000; i++)
d[i] = combine(d[i], s[2*i], s[2*i+1]);
I could of course manually spawn threads, but that is a lot more code than std::for_each, so it would be great to find an elegant way to do this with the standard library. So far I have found some not very elegant ways of using for_each, for instance:
Compute the index by using pointer arithmetic on the address of the array element.
Implement my own bogus iterator in the spirit of boost's counting_range.
Is there a better way to do this?
std::ranges should be able to help if you have access to c++20, you can iterate over the indexes rather than your data:
#include <ranges>
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<int> d(100);
std::ranges::iota_view indexes((size_t)0, d.size());
std::for_each(std::execution::par, indexes.begin(), indexes.end(), [&d](size_t i)
{
std::cout << i << "," << d[i] << "\n";
});
return 0;
}
You should be able to iterate over the indexes rather than the items. I think C++20 std::ranges gives you an easy way to do this, or you can use one of the Boost range methods. I'm not sure why you would consider rolling your own in the spirit of Boost counting_range when you could just, well, use Boost :-)
Having said that, I've actually opted for that roll-your-own approach, simply to make the code self-contained with neither C++20 nor Boost: feel free to replace paxrange with one of the other methods depending on your needs:
#include <iostream>
#include <algorithm>
// Seriously, just use Boost :-)
class paxrange {
public:
class iterator {
friend class paxrange;
public:
long int operator *() const { return value; }
const iterator &operator ++() { ++value; return *this; }
iterator operator ++(int) { iterator copy(*this); ++value; return copy; }
bool operator ==(const iterator &other) const { return value == other.value; }
bool operator !=(const iterator &other) const { return value != other.value; }
protected:
iterator(long int start) : value (start) { }
private:
unsigned long value;
};
iterator begin() const { return beginVal; }
iterator end() const { return endVal; }
paxrange(long int begin, long int end) : beginVal(begin), endVal(end) {}
private:
iterator beginVal;
iterator endVal;
};
int main() {
// Create a source and destination collection.
std::vector<int> s;
s.push_back(42); s.push_back(77); s.push_back(144);
s.push_back(12); s.push_back(6);
std::vector<int> d(5);
// Shows how to use indexes with multiple collections sharing index.
auto process = [s, &d](const int idx) { d[idx] = s[idx] + idx; };
paxrange x(0, d.size());
std::for_each(x.begin(), x.end(), process); // add parallelism later.
// Debug output.
for (const auto &item: s) std::cout << "< " << item << '\n';
std::cout << "=====\n";
for (const auto &item: d) std::cout << "> " << item << '\n';
}
The "meat" of the solution is the three lines in the middle of main(), where you set up a function for call-backs, one that takes the index rather than the item itself.
Inside that function, you use that index plus as many collections as needed, to set up the destination collection, very similar to what you desire.
In my case, I simply wanted the output vector to be the input vector but with the index added to each element, as per the output:
< 42
< 77
< 144
< 12
< 6
=====
> 42
> 78
> 146
> 15
> 10
There is a simple header-only library in Github which might help you.
Your minimal example can be parallelized like this. However, presumably due to cache cooling, the runtime will not scale down linearly with the number of cores.
#include "Lazy.h"
double combine(double a, double b, double c)
{
if (b > 0.5 && c < 0.4)
return a + std::exp(b * c + 1);
else if (b*c < 0.2)
return a * 0.8 + (1-c) * (1-b);
else
return std::exp(1.0 / a) + b + c;
}
// Generate index split for parallel tasks
auto getIndexPairs(std::size_t N, std::size_t numSplits)
{
std::vector<std::pair<std::size_t, std::size_t>> vecPairs(numSplits);
double dFrom = 0, dTo = 0;
for (auto i = 0; i < numSplits; ++i) {
dFrom = dTo;
dTo += N / double(numSplits);
vecPairs[i] = {std::size_t(dFrom), std::min(std::size_t(dTo), N)};
}
vecPairs[numSplits-1].second = N;
return vecPairs;
}
int main(int argc, char** argv) {
const std::size_t N = 100000000;
const std::size_t C = std::thread::hardware_concurrency(); // Number of parallel finder threads
std::vector<double> d(N);
std::vector<double> s(2*N);
// Fill d and s with some values
for (std::size_t i = 0; i < N; ++i) {
s[i] = double(i) / N;
s[i + N] = double(i + N) / N;
d[i] = N - i;
}
// Run combine(...) in parallel in C threads
Lazy::runForAll(getIndexPairs(N, C), [&](auto pr) {
for (int i=pr.first; i<pr.second; ++i)
d[i] = combine(d[i], s[2*i], s[2*i+1]);
return nullptr; // Dummy return value
});
}
#Alan Birtles answer does not work with a parallel execution policy, as it errors out to "static_assert failed: 'Parallel algorithms require forward iterators or stronger.'".
A potential alternative is to make an iterator vector, but it won't be as space-efficient.
std::vector<std::size_t> indexes(d.size());
std::iota(indexes.begin(), indexes.end(), 0);
std::for_each(std::execution::par, indexes.begin(), indexes.end(), [&](size_t i) {
std::cout << i << ',' << d[i] << '\n';
}
I want to write a template based function, which takes float vector as input and return vector type based on template. Below code is working fine with "int", "double", "float" etc but when I try things with datatype like "uint8_t", i got vector of required size. But when try to print values, I got empy line.
#include <iostream>
#include <string>
#include <vector>
template<typename T>
std::vector<T> convertDattype(std::vector<float> float_vec)
{
std::vector<T> vec;
vec.reserve( float_vec.size() ); // avoids unnecessary reallocations
std::transform( float_vec.begin(), float_vec.end(),
std::back_inserter( vec ),
[](const float &arg) { return static_cast<T>(arg); } );
return vec;
}
int main()
{
const uint64_t VEC_COUNT = 10;
std::vector<float> float_vec;
float_vec.reserve(VEC_COUNT);
for (unsigned int i = 0; i < VEC_COUNT; ++i) {
float val = static_cast<float>((rand() % 100) / 3.0f);
float_vec.push_back(val);
}
std::vector<uint8_t> data = convertDatatype<uint8_t>(float_vec);
for(auto a : data) {
std::cout << a << std::endl;
}
}
I don't know whether std::transform will work or not.
I just want to convert datatype of given vector to T.
Any help would be appreciated. Thanks
Use this to convert a vector's data type.
intVector = std::vector<uint8_t>(data.begin(), data.end());
I coded the following function to convert a std::vector of uint8_t to an ascii hexadecimal string (gnu++98 standard).
...
string uint8_vector_to_hex_string(const vector<uint8_t>& v) {
stringstream ss;
vector<uint8_t>::const_iterator it;
for (it = v.begin(); it != v.end(); it++) {
char hex_char[2];
sprintf(hex_char, "%x", *it);
ss << "\\x" << hex_char;
}
return ss.str();
}
...
It works fine. I was wondering if there is a better way to do this transformation, maybe using not both the stringstream object and the sprintf function. Any suggestion?
You could use the stringstream directly to do hex formatting:
#include <string>
#include <sstream>
#include <iostream>
...
string uint8_vector_to_hex_string(const vector<uint8_t>& v) {
stringstream ss;
ss << std::hex << std::setfill('0');
vector<uint8_t>::const_iterator it;
for (it = v.begin(); it != v.end(); it++) {
ss << "\\x" << std::setw(2) << static_cast<unsigned>(*it);
}
return ss.str();
}
...
(Note: The answer is for standard C++; minor modifications regarding range iteration may be needed to work in older dialects. I consider those immaterial to the core problem of algorithmic efficiency that's salient to the question.)
You can save yourself a ton of work by realizing that you basically know the answer in advance and don't need to do all this dynamic work.
std::string uint8_vector_to_hex_string(const vector<uint8_t>& v)
{
std::string result;
result.reserve(v.size() * 2); // two digits per character
static constexpr char hex[] = "0123456789ABCDEF";
for (uint8_t c : v)
{
result.push_back(hex[c / 16]);
result.push_back(hex[c % 16]);
}
return result;
}
In the spirit of "recognizing the algorithm", here's a separated algorithm for place-value formatting of numeric sequences. First the use case:
#include <iostream>
#include <string>
#include <vector>
// bring your own alphabet
constexpr char Alphabet[] = "0123456789ABCDEF";
// input
std::vector<unsigned char> const v { 31, 214, 63, 9 };
// output (Note: *our* responsibility to make allocations efficient)
std::string out;
out.reserve(v.size() * 2);
// the algorithm
place_value_format<char, // output type
2, // fixed output width
16>( // place-value number base
v.begin(), v.end(), // input range
std::back_inserter(out), // output iterator
Alphabet); // digit representation
Now the algorithm:
#include <algorithm>
#include <iterator>
template <typename Out, std::size_t NDigits, std::size_t Base,
typename InItr, typename OutItr>
OutItr place_value_format(InItr first, InItr last, OutItr out, Out const * digits)
{
for (; first != last; ++first)
{
Out unit[NDigits];
auto val = *first;
for (auto it = std::rbegin(unit); it != std::rend(unit); ++it)
{
*it = digits[val % Base];
val /= Base;
}
out = std::copy(std::begin(unit), std::end(unit), out);
}
return out;
}
If you don't mind using Boost in your project you can use boost::hex
#include <boost/algorithm/hex.hpp>
std::string uint8_vector_to_hex_string(const std::vector<uint8_t> & v) {
std::string result;
result.reserve(v.size() * 2);
boost::algorithm::hex(v.begin(), v.end(), std::back_inserter(result));
return result;
}
I would go for something with no dependencies on other classes:
std::string uint8_vector_to_hex_string(const std::vector<uint8_t>& v) {
std::string result;
result.resize(v.size() * 2);
const char letters[] = "0123456789ABCDEF";
char* current_hex_char = &result[0];
for (uint8_t b : v) {
*current_hex_char++ = letters[b >> 4];
*current_hex_char++ = letters[b & 0xf];
}
return result;
}