Minimization of (z-xi)^2
Minimization of (z-xi)^2
如果我想找到一个median
(它相当于最小化一个函数|z - xi|(,我可以使用以下code snippet
:
std::vector<int> v{5, 6, 4, 3, 2, 6, 7, 9, 3};
std::nth_element(v.begin(), v.begin() + v.size()/2, v.end());
std::cout << "The median is " << v[v.size()/2] << 'n';
有没有这样的东西,找到最小化 (z-xi(^2 的"median"
?也就是说,我想找到数组中的一个元素,其中这些函数的总和将是最小的。
谓词比较(z - xi) ^ 2
找到nth_element()
,你可以将相应的逻辑添加到二进制谓词中,你可以选择传递给nth_element()
:
auto trans = [=](int xi){ return (z - xi) * (z - xi); };
std::nth_element(v.begin(), v.begin() + v.size() / 2, v.end(),
[&](int v0, int v1) { return trans(v0) < trans(v1); });
从这个问题来看,不清楚z
或xi
是变化变量。从它的外观来看,我认为xi
应该是x
i。如果z
正在更改,只需重命名 lambda trans
中的参数(我刚刚在捕获中也给出了一个=
......
你的问题至少在两个不同的层面上起作用:你问如何在 C++11 中习惯性地实现某种算法,同时你要求一种有效的算法来计算整数列表的平均值。
您正确地观察到,要计算中位数,我们所要做的就是运行 QuickSelect 算法,k
设置为 等于 n/2
.在C++标准库中,快速选择拼写为std::nth_element
:
int v[] = { 5, 6, 4, 3, 2, 6, 7, 9, 3 };
const int k = std::size(v) / 2;
std::nth_element(std::begin(v), &v[k], std::end(v)); // mutate in-place
int median = v[v.size()/2]; // now the k'th element is
(有关std::size
,请参阅提案N4280,即将在您附近的C++17! 在此之前,请使用您最喜欢的 NELEM 宏,或返回到使用堆分配的vector
。
此快速选择实现实际上与"查找数组元素 xk 以便 ∑i |x i − xk|被最小化了。我的意思是,它在数学上是等价的,是的,但是代码中没有任何内容对应于对整数求和或减去。
"查找数组元素 xk 使得 ∑i |x i − xk| 最小化"是
int v[] = { 5, 6, 4, 3, 2, 6, 7, 9, 3 };
auto sum_of_differences = [v](int xk) {
int result = 0;
for (auto&& xi : v) {
result += std::abs(xi - xk);
}
return result;
};
int median =
std::min_element(std::begin(v), std::end(v), [](int xa, int xb) {
return sum_of_differences(xa) < sum_of_differences(xb);
});
这是一个非常低效的算法,因为QuickSelect做同样的工作。但是,扩展此代码以使用您想要"最小化总和"的任何数学函数是微不足道的。这是相同的代码框架,但使用函数"平方差"而不是"差":
int v[] = { 5, 6, 4, 3, 2, 6, 7, 9, 3 };
auto sum_of_squared_differences = [v](int xk) {
int result = 0;
for (auto&& xi : v) {
result += (xi - xk) * (xi - xk);
}
return result;
};
int closest_element_to_the_mean =
std::min_element(std::begin(v), std::end(v), [](int xa, int xb) {
return sum_of_squared_differences(xa) < sum_of_squared_differences(xb);
});
在这种情况下,我们还可以找到一种改进的算法;即,预先计算平均值,然后扫描数组以查找最接近该平均值的元素:
int v[] = { 5, 6, 4, 3, 2, 6, 7, 9, 3 };
double actual_mean = std::accumulate(std::begin(v), std::end(v), 0.0) / std::size(v);
auto distance_to_actual_mean = [=](int xk) {
return std::abs(xk - actual_mean);
};
int closest_element_to_the_mean =
std::min_element(std::begin(v), std::end(v), [](int xa, int xb) {
return distance_to_actual_mean(xa) < distance_to_actual_mean(xb);
});
(P.S. – 请记住,上述代码片段都不应在实践中使用,除非您绝对确定不需要关心整数溢出、浮点舍入错误和许多其他数学问题。
实数 z 是平均值 z* = (1/n( ∑i∈{1,2,...,n} xi.您希望使用比较器调用std::min_element
,该比较器将 x i 视为小于 xj,当且仅当 |n xi - n z*|<|n xj - n z*|(我们使用 n z* = ∑i∈{1,2,...,n} xi 来避免浮点运算;有一些方法可以减少所需的额外精度(。
- Usages of std::move
- 使用 [] 运算符时"binding reference of type discards qualifiers"
- 如何处理 c++ 中类实现中的"invalid use of non-static data member"?
- 具有变量Number of Arguments的std::函数的矢量
- Capacity of a deque
- Deprecation of _writeBarrier()
- constexpr begin of a std::array
- 如何调整 std::vector of Eigen::MatrixXd 的大小
- C++ "error: invalid use of void expression"
- 我看到"use of undeclared identifier"错误,有人可以告诉我如何解决它吗?
- 赛通"Cannot take address of memoryview slice"
- C++ Version Of Double.longBitsToDouble
- 收到错误"invalid use of non-static data member 'stu::n' "
- C++ Usage of AsyncCallback
- 错误:"Left of getValue must have class/struct/union"
- Centos7 g++ "to_string is not in a member of std"
- 在C++中使用 Catch 测试框架编译错误"error: expected ';' at end of declaration list"
- 传递 std::vector of std::shared_ptr,而不是更新对象
- C++/SDL "initial value of reference to a non-const must be an lvalue"
- Minimization of (z-xi)^2