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
正在更改,只需重命名lambda
trans
中的参数(我刚才在捕获中也给出了一个
=

给定一个整数数组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);
    });