C++17实现类似Python的支持double类型的range生成函数
C++17 实现double类型的类Python range生成函数
实现思路
double类型的range实现核心要解决浮点精度误差问题,不能直接套用整数的循环比较逻辑,同时要适配正负步长的场景,避免死循环。具体逻辑如下:
- 先做非法输入校验:步长为0、步长方向和区间方向不匹配的场景直接返回空容器
- 预计算元素个数提前分配vector空间,避免频繁扩容带来的性能损耗
- 浮点比较引入动态epsilon容差,根据起始/结束值的量级调整阈值,避免精度误差导致的元素丢失或多余
完整实现代码
#include <vector> #include <iostream> #include <cmath> #include <limits> std::vector<double> generateRange(double start, double end, double step) { // 步长为0属于非法输入,直接返回空 const double step_abs = std::fabs(step); if (step_abs < std::numeric_limits<double>::epsilon()) { return {}; } const double range_diff = end - start; // 步长与区间方向不匹配,无法生成有效序列,直接返回空 if (range_diff * step < 0) { return {}; } // 预计算元素个数,提前分配空间提升性能 const size_t elem_count = static_cast<size_t>(std::ceil(range_diff / step)) + 1; std::vector<double> res; res.reserve(elem_count); // 动态计算浮点比较容差,适配不同量级的数值区间 const double eps = std::numeric_limits<double>::epsilon() * std::max(std::fabs(start), std::fabs(end)) * 100; double current = start; while ((step > 0 && current <= end + eps) || (step < 0 && current >= end - eps)) { res.push_back(current); current += step; } // 剔除精度误差导致超出区间的最后一个异常元素 if (!res.empty()) { const double& last = res.back(); if ((step > 0 && last > end + eps) || (step < 0 && last < end - eps)) { res.pop_back(); } } return res; } int main() { // 测试用例:返回 [10, 10.5, 11, 11.5, 12] auto range = generateRange(10, 12, 0.5); for (auto i : range) { std::cout << i << ' '; } // 输出:10 10.5 11 11.5 12 // 也支持负步长场景:generateRange(12, 10, -0.5) 会返回逆序序列 return 0; }
注意说明
- 容差阈值可以根据业务的精度要求调整,上述代码中的100倍epsilon适配绝大多数常规使用场景
- 支持正负步长,只要步长方向和区间方向匹配即可生成对应序列
- 如果需要更高的精度,也可以替换为long double类型实现,逻辑完全一致
内容的提问来源于stack exchange,提问作者Sergo Longid
相关产品推荐
相关产品推荐

