C++ (z-xi)^2的极小化
如果我想找到一个C++ (z-xi)^2的极小化,c++,algorithm,c++11,median,minimize,C++,Algorithm,C++11,Median,Minimize,如果我想找到一个中值(它相当于最小化一个函数| z-xi),我可以使用以下代码片段: 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'; std::向量v{5,6,4,3
中值
(它相当于最小化一个函数| z-xi),我可以使用以下代码片段
:
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';
std::向量v{5,6,4,3,2,6,7,9,3};
std::n_元素(v.begin(),v.begin()+v.size()/2,v.end());
std::cout如果要根据比较(z-xi)^2的谓词查找n_元素()
,只需将相应的逻辑添加到二进制谓词,您可以选择传递到n_元素()
:
autotrans=[=](int-xi){return(z-xi)*(z-xi);};
std::n_元素(v.begin(),v.begin()+v.size()/2,v.end(),
[&](intv0,intv1){返回trans(v0)
从这个问题来看,z
或xi
是否是变化变量并不清楚。从外观上看,我假设xi
是x
I。如果z
正在更改,只需重命名lambdatrans
中的参数(我刚才在捕获中也给出了一个=
。给定一个整数数组x1,x2,…,xn,最小的实数z∑i&in;{1,2,…,n}(z-xi)2是平均值z*=(1/n)∑i&in;{1,2,…,n}席。你想调用<代码> STD::MiNyMease/Cuff>,比较器将XI小于XJ,当且仅当席席-N Z** << n XJ-N Z*()时,我们使用n Z*=∑I&in;{1,2,…,n}席以避免浮点运算;有减少额外精度的方法。 < p>至少在两个不同的层次上工作:你问如何在C++ 11中用惯用的方法实现某个算法,同时你需要一个有效的算法来计算整数列表的平均值
您正确地观察到,要计算中位数,我们所要做的就是运行k
设置为n/2
。在C++标准库中,QuestScLoad被拼写为:
(有关std::size
,请参阅建议,在此之前,请使用您最喜欢的NELEM宏,或返回使用堆分配向量
)
这个QuickSelect实现与“查找数组元素xk以便∑i|xi− 我的意思是,它在数学上是等价的,是的,但代码中没有与求和或减法整数相对应的东西
“查找数组元素xk以便∑i|xi− 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);
});
intv[]={5,6,4,3,2,6,7,9,3};
差异的自动求和=[v](int xk){
int结果=0;
对于(Auto&席:V){
结果+=std::abs(xi-xk);
}
返回结果;
};
整数中值=
std::min_元素(std::begin(v),std::end(v),[](intxa,intxb){
返回差异之和(xa)<差异之和(xb);
});
这是一个效率极低的算法,因为QuickSelect也做同样的工作。
然而,将这段代码扩展到处理任何想要“最小化和”的数学函数是很简单的。下面是相同的代码框架,但函数是“平方差”,而不是“差”:
intv[]={5,6,4,3,2,6,7,9,3};
平方差的自动求和=[v](int xk){
int结果=0;
对于(Auto&席:V){
结果+=(xi-xk)*(xi-xk);
}
返回结果;
};
int最接近于平均值的元素=
std::min_元素(std::begin(v),std::end(v),[](intxa,intxb){
返回平方差之和(xa)<平方差之和(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);
});
intv[]={5,6,4,3,2,6,7,9,3};
双实际平均值=std::累加(std::开始(v),std::结束(v),0.0)/std::大小(v);
自动距离到实际平均值=[=](int xk){
返回标准::绝对值(xk-实际平均值);
};
int最接近于平均值的元素=
std::min_元素(std::begin(v),std::end(v),[](intxa,intxb){
返回距离_至_实际_平均值(xa)<距离_至_实际_平均值(xb);
});
(另请记住,以上代码片段都不应用于实践,除非您完全确定不需要关心整数溢出、浮点舍入错误和大量其他数学问题。)谢谢您的回复。不幸的是,这并不是那么简单<代码>z
不是常数z
是数组的一个元素,在这里达到了最小值。@丹尼斯,你应该澄清一下,在你的问题中,xi
是常数吗?我假设你的意思是x
I是变量。把论点改名…@DietmarKühl,谢谢你的帮助。我理解一切。请注意,(z-xi)
2所暗示的顺序与|z-xi
所暗示的顺序相同,但是使用abs(z-xi)
可能比平方(z-xi)
更有效。你完全正确。我找到了函数的导数。你的答案很好!非常感谢。
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);
});
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);
});