#c #algorithm #c 17
Вопрос:
Я пытаюсь создать функцию, которая заполняет мой вектор значениями от начала до конца определенным шагом. Для типа double и версии C 17. Есть идеи, как это сделать?
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 << ' ';
}
Для int это был бы очень простой цикл, но для double…
Комментарии:
1. Проверьте пример: en.cppreference.com/w/cpp/iterator/iterator
2. Вы говорите, что это был бы простой цикл для int. Можете ли вы показать, как это будет выглядеть, и описать, что, по вашему мнению, будет мешать адаптации к работе для двойников?
3. @nathan-пирсон Поскольку числа с плавающей запятой представляют реальные числа, часто ошибочно полагают, что они могут точно представлять любую простую дробь. Мы можем использовать double in для цикла.
4. Учитывая , что вы могли бы написать это для
int
, я подозреваю, что если бы вы попытались написать то же самое дляdouble
, у вас либо все получилось бы, либо возник бы более конкретный вопрос о том, почему ваш код не идеален.5. Попробуйте продумать, каков ваш желаемый результат. Попробуйте написать реализацию, которая его создает. Если у вас есть проблемы, спросите об этих конкретных проблемах.
Ответ №1:
Вы можете, например, написать простой цикл для генерации нужного вам вектора.
Однако range
функция в python возвращает не список, а генератор, что намного быстрее. Вы также должны возвращать генератор (диапазон) в C , а не возвращать вектор. Реализация генератора немного более продвинута.
Стандартная библиотека поставляется с инструментами, которые можно использовать для создания такого генератора. Вот ваш пример:
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);
Ответ №2:
Я не думаю, что вам абсолютно необходимо хранить значения в векторе, прежде чем повторять их.
Я бы сделал что-то подобное
/**
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 amp;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 amp;value: generate_range(10, 12, 0.5))
{
std::cout << value << ' ';
}
std::cout << 'n'; // 10 10.5 11 11.5 12
for(const auto amp;value: generate_range(239.99, 237.36, 1))
{
std::cout << value << ' ';
}
std::cout << 'n'; // 237.36 238.36 239.36
return 0;
}
Обратите внимание, что !=
на самом деле тесты <=
; это некрасиво, но это работает.
Эта функция возвращает то, что предлагает, begin()
и end()
функции-члены, чтобы цикл поиска диапазона мог ее использовать.
правка: добавлена минимальная/максимальная для инвертированных границ.
Комментарии:
1. thx так много, но я пробую эти данные, и они не работают: generate_range(239.99, 237.36, 1) Я ожидал увидеть 238, Но программа ничего не отображала
2. Ах, ты тоже хочешь, чтобы все пошло в обратном направлении?
3. @SergoLongid Я отредактировал, следовательно, но я не уверен в том, чего вы точно ожидаете.
Ответ №3:
Мое решение проблемы:
#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 amp;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 << ' ';
}
если у вас есть какие-либо вопросы о функциях, которые я использовал, не стесняйтесь спрашивать 🙂