std::reduce 似乎将结果转换为整数
std::reduce seems to convert results to integers
我正在比较这两个函数:
double polynomials(const vector<double> & coeffs, double x) {
double sum = 0.0;
double factor = 1.0;
for (double coeff: coeffs) {
sum += coeff * factor;
factor *= x;
}
return sum;
}
和
double algorithm_polynomials(const vector<double> & coeffs, double x) {
return reduce(execution::seq, cbegin(coeffs), end(coeffs), 0, [factor=1.0, x](double sum, double coeff) mutable {
double curr_sum = sum + coeff * factor;
factor *= x;
return curr_sum;
});
}
对于整数系数和整数 x,这两个函数的结果是等效的。但对于实际值,结果会有所不同。第一个函数给出的是正确的,而第二个函数给出的总是整数(不一定接近实际答案(。
我的猜测是,每个中间值在求和之前都被转换为整数,但我不明白为什么会发生这种情况,或者我该如何解决它。
要运行此代码,请使用
#include <numeric>
#include <vector>
#include <algorithm>
#include <execution>
using namespace std;
需要带有 -std=C++17 标志的 GCC 9 或更高版本,并从 2019 年开始链接到 TBB。
编辑:谢谢大家指出我忽略的初始值类型。
我感到有点羞愧,因为没有看到它,以及使用不当的reduce函数(由于可变的lambda而无法并行化(。
为了救赎自己,我在这里添加一种方法来使其并行......
class counter: public std::iterator<
std::random_access_iterator_tag, // iterator_category
size_t, // value_type
size_t, // difference_type
const size_t*, // pointer
size_t // reference
>{
size_t num = 0;
public:
explicit counter(size_t _num) : num(_num) {}
counter& operator++() {num += 1; return *this;}
counter operator++(int) {counter retval = *this; ++(*this); return retval;}
bool operator==(counter other) const {return num == other.num;}
bool operator!=(counter other) const {return !(*this == other);}
counter& operator+=(size_t i) { num += i; return *this; }
counter& operator-=(size_t i) { num -= i; return *this; }
counter operator +(counter &other) const { return counter(num + other.num);}
counter operator -(counter &other) const { return counter(num - other.num); }
counter operator +(size_t i) const { return counter(num + i); }
counter operator -(size_t i) const {return counter(num - i); }
reference operator*() const {return num;}
};
double better_algorithm_polinomials(const vector<double> & coeffs, double x) {
//this has the advantage of being easily parallelized
return transform_reduce(execution::par, cbegin(coeffs), end(coeffs), counter(0), 0.0, plus{}, [x](double coeff, size_t index) { return coeff * pow<double>(x, index); });
}
您正在调用的std::reduce()
的版本:
template<class ExecutionPolicy, class ForwardIt, class T, class BinaryOp>
T reduce(ExecutionPolicy&& policy,
ForwardIt first, ForwardIt last, T init, BinaryOp binary_op);
您可以清楚地看到返回值使用与init
参数相同的数据类型,在您的情况下,该参数被推导出为int
,这就是为什么结果是int
.
若要使返回值改为double
,只需在init
参数中将文本0
更改为0.0
:
return reduce(execution::seq, cbegin(coeffs), cend(coeffs), 0.0, ...);
如果您查看std::reduce()
的声明,您会发现将init
值作为输入的std::reduce()
版本使用其类型作为返回类型。根据 cppreference.com,您将看到以下内容:
template<class InputIt, class T>
T reduce(InputIt first, InputIt last, T init);
或者,在您的情况下(感谢雷米·勒博注意到(:
template<class ExecutionPolicy, class ForwardIt, class T, class BinaryOp>
T reduce(ExecutionPolicy&& policy,
ForwardIt first, ForwardIt last, T init, BinaryOp binary_op);
因此,init
值的类型决定了输出值的类型,并且您正在传递一个整数文本(即0
(。尝试传递双精度文字(即0.0
(。
std::accumulate()
也有同样的陷阱。返回类型(以及累加器变量的类型(与init
参数的类型相同。
由于0
是一个int
,结果也是一个int
。请改用0.0
。
相关文章:
- 努力将整数转换为链表。不知道我在这里做错了什么
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 如何在C++中将整数转换为其数字数组
- 尝试将字符串/字符转换为整数会产生意外结果
- 如何使用C++将字符串中的字符转换为整数变量
- 如何将整数字符串转换为整数的二维向量?
- 如果整数与指针大小相同,则重新解释将整数转换为指针双射是否具有双射作用?
- 使用 "stringstream " 将字符串转换为整数
- 将字符串转换为浮点数或整数,而无需使用内置函数(如 atoi 或 atof)
- 如何检测 std::vector::emplace_back 上的隐式转换损失整数精度
- 如何防止双精度值到整数的隐式转换
- 为什么此指针值不能转换为整数的规则是什么?
- 如何解决隐式转换丢失整数精度:'size_t'(又名"无符号长")到'int'警告?
- 在 C++ 中将整数数组转换为位集表示形式的最佳方法?
- 为什么在将 void 指针转换为整数指针时出现分段错误
- 将字符串(可以是十进制字符串或十六进制字符串)转换为整数C++
- 整数类型应该显式转换(例如"int"到"无符号")还是只会增加混乱?
- 如何使用 STL 算法将整数向量转换为字符串向量?
- 无法将"整数 (*)[m]"转换为"整数 (*)[100000]
- 静态强制转换允许转换对象指针,但不允许转换整数