3

My question is how to choose n element from vec.begin() to vec.end() such that we almost cover all the vector elements?

vector<double> take_100_samples(vector<double>& in)
{
  vector<double> vec(100);
  double step = (in.size() - 1) / (100 - 1);

// sampling process

  return vec;
} 

for example if in vector has size of 200, we choose every two element of it (i.e. in[0], in[2] , in[4], ... ,in[199]) but what if the size is not dividable by 100?

Is there efficient way for doing that?
Regards

leiyc
  • 903
  • 11
  • 23
student_11
  • 142
  • 6
  • 15
    probably what you want is [std::sample](https://en.cppreference.com/w/cpp/algorithm/sample) – Albin Paul Nov 07 '18 at 07:51
  • 1
    What do you mean with "cover all the elements" when you take only a sample ? Is it about the range of values stored in the vector ? Is it about making sure that you take at least the first and the last ? What if the in vector has less than 100 elements ? – Christophe Nov 07 '18 at 07:51
  • @Christophe i.e. for vec with size 200 and step 2 we almost cover all the element...just a good step definition. and always we sure that the input vector has size greater than 100 – student_11 Nov 07 '18 at 07:58
  • 1
    I think `std::sample` with a random_device is not adequate here, since it does not populate the result uniformly. Meaning with 200 Elements it is not guarated to take every second element! – user1810087 Nov 07 '18 at 09:18
  • Exactly, there is no randomness in the question, it's uniformly sampled, not stochastic uniform sampling. – Matthieu Brucher Nov 07 '18 at 09:24

2 Answers2

2

The usual way to do so is to get the floating point fraction and then rounding it to an integer:

double step = in.size() / 100.;

for(int i = 0; i < 100; ++i)
{
    auto index = std::lround(i * step);
    // use index
}

Of course, adapt the step computation as you did as well as the loop if you want to get the first and last elements all the time.

Matthieu Brucher
  • 21,634
  • 7
  • 38
  • 62
1

My interpretation is that you want to downsample a signal with an asynchronous frequency.

One way to do this is to implement a kind of Digital PLL (Phase Lock Loop).

Let us assume that you have N = 1030 elements at input and that you want to get K = 100 elements.
The average rate is equal to rate = 10.3. In practice, you will have to use a step equal to 10 or 11 depending of the current position of the indices.

If you are in "advance" : step = 10 (slow down)
If you are "late" : step = 11 (speed up)

Test to know if you late or in advance:
The current "read" index i is equal to the sum of the former steps. k is the output index
if i < rate*k : you are late
else you are in advance

This is the basic idea. Some small adaptations are possible, for example to insure getting the last element.

EDIT: I just 'rediscovered' Mathieu Brucher's solution. In my first too fast reading of it, I was misled by the original error (corrected) on step calculation in his answer. It is clear that results will be equivalent, except that Mathieu Brucher's implementation is simpler. In this situation, the only interest (?) of my answer is to provide another interpretation of the process

Damien
  • 4,809
  • 4
  • 15
  • 20