1

I'm trying to create a function that fills my vector with values from beginning to end with a certain step. For type double and C++ 17 version. Any idea how to do this?

vector<double> generateRange(double start, double end, double step)
{


}

int main()
{
    // return [10, 10.5, 11,...., 12]
    auto range = generateRange(10, 12, 0.5);

    for (auto i : range)
        std::cout << i << ' ';
}

For int it would be a very simple loop, but for double...

9
  • 1
    Check the example: en.cppreference.com/w/cpp/iterator/iterator Commented Aug 24, 2021 at 18:28
  • 1
    You say it would be a simple loop for int. Can you show what that would look like and describe what you think would be the sticking points adapting it to work for doubles? Commented Aug 24, 2021 at 18:30
  • @nathan-pierson Because floating-point numbers represent real numbers, it is often mistakenly assumed that they can represent any simple fraction exactly. We can use double in for loop. Commented Aug 24, 2021 at 18:34
  • 3
    Given that you could write this for int, I suspect that if you tried writing the same for double, you would either succeed or have a more specific question about why your code isn't perfect. Commented Aug 24, 2021 at 18:37
  • 2
    Try thinking through what your desired output is. Try to write up an implementation that produces it. If you have problems, ask about those specific issues. Commented Aug 24, 2021 at 18:43

3 Answers 3

3

You can for example write a simple loop to generate vector that you want.

However, the range function in python doesn't return a list but a generator, which is much faster. You should be returning a generator (range) in C++ as well instead of returning a vector. Implementing a generator is a bit more advanced.

The standard library comes with tools that can be used to build such generator. Here is your example:

auto step_fun = [=](auto x) { return x * step + start; };
auto end_pred = [=](auto x) { return x <= end; };
auto range =
    std::views::iota(0)
    | std::views::transform(step_fun)
    | std::views::take_while(end_pred);
Sign up to request clarification or add additional context in comments.

Comments

1

I don't think you absolutely need to store the values in a vector before iterating over them.

I would do something like this

/**
  g++ -std=c++17 -o prog_cpp prog_cpp.cpp \
      -pedantic -Wall -Wextra -Wconversion -Wno-sign-conversion \
      -g -O0 -UNDEBUG -fsanitize=address,undefined
**/

#include <iostream>
#include <algorithm>

inline
auto // iterable
generate_range(double from_count,
               double to_count,
               double step)
{
  struct Iter
  {
    double count;
    double step;
    bool operator!=(const double &rhs) const { return count<=rhs; } // oh!!!
    void operator++() { count+=step; }
    auto operator*() const { return count; }
  };
  struct Enumerate
  {
    double from_count;
    double to_count;
    double step;
    auto begin() { return Iter{from_count, step}; }
    auto end() { return to_count; }
  };
  return Enumerate{std::min(from_count, to_count),
                   std::max(from_count, to_count),
                   step};
}

int
main()
{
  for(const auto &value: generate_range(10, 12, 0.5))
  {
    std::cout << value << ' ';
  }
  std::cout << '\n'; // 10 10.5 11 11.5 12
  for(const auto &value: generate_range(239.99, 237.36, 1))
  {
    std::cout << value << ' ';
  }
  std::cout << '\n'; // 237.36 238.36 239.36
  return 0;
}

Note that != actually tests <=; it's ugly, but it works.

This function returns something that offers begin() and end() member-functions so that a range-for loop can use it.

edit: added min/max for inverted bounds.

3 Comments

thx so much, but i try this data and it doesn't work: generate_range(239.99, 237.36, 1) I expected to see 238 But the program did not display anything
Ah, you want it to go backwards too?
@SergoLongid I edited consequently, but I'm not certain of what you precisely expect.
0

My solution to problem:

#include <vector>
using std::vector;
#include <iostream>
using std::cout;
#include <algorithm>

vector<double> generateRange(double start, double end, double step)
{
    int vector_size = (end - start) / step;
    vector<double> values(vector_size);
    std::for_each(begin(values), std::end(values),
    [start, step, i = 0](double &actual) mutable {
        actual = start + step * i;
        i++;
    });
    return values;

}

int main()
{
    // return [10, 10.5, 11,...., 12]
    auto range = generateRange(10, 12, 0.5);

    for (auto i : range)
        std::cout << i << ' ';
}

if you have any question about functions i used don't hesitate to ask :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.