Minimization of (z-xi)^2

Minimization of (z-xi)^2

本文关键字:z-xi of Minimization      更新时间:2023-10-16

如果我想找到一个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); });

从这个问题来看,不清楚zxi是变化变量。从它的外观来看,我认为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 ixk|被最小化了。我的意思是,它在数学上是等价的,是的,但是代码中没有任何内容对应于对整数求和或减去。

"查找数组元素 xk 使得 ∑i |x ixk| 最小化"是

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. – 请记住,上述代码片段都不应在实践中使用,除非您绝对确定不需要关心整数溢出、浮点舍入错误和许多其他数学问题。

给定一个数组 x 1, x 2, ..., x n 的整数,最小化 ∑i&in;{1,2,...,n} (z - x i(2 的

实数 z 是平均值 z* = (1/n( ∑i&in;{1,2,...,n} xi.您希望使用比较器调用std::min_element,该比较器将 x i 视为小于 xj,当且仅当 |n xi - n z*|<|n xj - n z*|(我们使用 n z* = ∑i&in;{1,2,...,n} xi 来避免浮点运算;有一些方法可以减少所需的额外精度(。