Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 获取C+中的中值+;_C++_Algorithm_C++11_Max_Min - Fatal编程技术网

C++ 获取C+中的中值+;

C++ 获取C+中的中值+;,c++,algorithm,c++11,max,min,C++,Algorithm,C++11,Max,Min,考虑三个值x、y、z 得到中间值(不是平均值,而是既不是min也不是max的值)的公式是什么 这看起来像是作弊,但是:x+y+z-min-max这比艾伦的诡计要难看一点,但它不会导致溢出,也不会导致数字错误,等等: int x, y, z, median; ... if (x <= y && y <= z || y >= z && y <= x) median = y; else if (y <= x && x &l

考虑三个值
x、y、z

得到中间值(不是平均值,而是既不是
min
也不是
max
的值)的公式是什么


这看起来像是作弊,但是:
x+y+z-min-max

这比艾伦的诡计要难看一点,但它不会导致溢出,也不会导致数字错误,等等:

int x, y, z, median;
...

if (x <= y && y <= z || y >= z && y <= x) median = y;
else if (y <= x && x <= z || x >= z && x <= y) median = x;
else median = z;

要同时以对称方式找到所有三个:

min = x; med = y; max = z;

if (min > med) std::swap(min, med);
if (med > max) std::swap(med, max);
if (min > med) std::swap(min, med);
艾伦“欺骗”的一种变体,它(有时)可以防止溢出:

#include <iostream>
#include <algorithm>

using namespace std;
int main(int argc, char *argv[]) {
    double a = 1e308;
    double b = 6e306;
    double c = 7.5e18;

    double mn = min(a,min(b,c));
    double mx = max(a,max(b,c));
    double avg = mn + (mx-mn)*0.5;
    double mid = a - avg + b - avg + c;

    cout << mid << endl;
}
它利用二进制搜索中常用的avg公式来防止溢出:

#include <iostream>
#include <algorithm>

using namespace std;
int main(int argc, char *argv[]) {
    double a = 1e308;
    double b = 6e306;
    double c = 7.5e18;

    double mn = min(a,min(b,c));
    double mx = max(a,max(b,c));
    double avg = mn + (mx-mn)*0.5;
    double mid = a - avg + b - avg + c;

    cout << mid << endl;
}
两个值的平均值可计算为
low+(high-low)/2

但是,它只适用于正值。可能的备选方案包括Alan的答案,或者简单地
(x+y)/2
进行平均值计算

请注意,双精度在这里起作用,可能会导致
mid
-计算中出现问题。它对正整数非常有效:)

注释中共享的答案:

const double mid = std::max(std::min(x,y),std::min(std::max(x,y),z));
编辑-正如艾伦指出的,我错过了一个案子。我现在给出了一个更直观的证明。 直接证明:不丧失x和y的一般性。
从最里面的表达式开始,
min(max(x,y),z)

  • 如果它返回z,我们已经找到了关系:max(x,y)>z。然后表达式的计算结果为
    max(min(x,y),z)
    。通过这一点,我们能够确定min(x,y)和z之间的关系。
    如果min(x,y)>z,则z小于x和y两者(当关系变为:max(x,y)>min(x,y)>z)。因此,min(x,y)实际上是中位数,
    max(min(x,y),z)
    返回该值。
    如果min(x,y),那么z实际上是中位数(作为min(x,y)
  • 如果它返回x,那么xmax(min(x,y),x)。由于max(x,y)计算为x,min(x,y)计算为y。获取关系z>x>y。我们返回x和y的最大值(表达式变为
    max(y,x)
    ),即x和中位数。(注意y的证明是对称的)
  • 验证结束


    旧校样-注意它不完整(直接): 在不丧失一般性的情况下: 假设x>y>z
    x和y的最小值是y。最小值(x和y的最大值),z是z。
    y和z的最大值为y,即中间值

    假设x=y>z
    x和y的最小值等于x。最小值(x和y的最大值为x)和z为z.
    以上两项的最大值为x,即中值

    假设x>y=z
    x和y的最小值是y。最小值(x和y的最大值为x)和z为z.
    以上两项的最大值为y,即中值

    最后,假设x=y=z

    三个数字中的任何一个都是中位数,使用的公式将返回一些数字。

    最好的方法是使用通用的中位数函数模板。不需要复制、交换或数学运算

    template <typename T>
    const T& median(const T& a, const T& b, const T& c)
    {
        if (a < b)
            if (b < c)
                return b;
            else if (a < c)
                return c;
            else
                return a;
        else if (a < c)
            return a;
        else if (b < c)
            return c;
        else
            return b;
    }
    
    模板
    常数T和中间带(常数T&a、常数T&b、常数T&c)
    {
    if(a
    也许没有一个简洁的对称公式?@AbhishekBansal如果它们都相等呢?如果只有两个相等呢?仅供参考,这称为中位数。随便挑一个。然后,你的应用程序将工作1/3的时间,这比我当前的应用程序要多得多。顺便说一句,在C++11中,
    min
    可以重写
    std::min({x,y,z})
    。我喜欢它。唯一的问题是溢出。@keyser:是的,所以也值得发布一个不同的答案,以防万一。此外,这不一定返回变量,只返回值。@Laszlo True(尽管可以说这是min和max的错误特性)。因为我们没有参考答案,所以没关系。你可以在没有mix和max的情况下获得med,因此它们的限制是不必要的。据我所知,至少有两个选项,或者不使用min和max。如果您想要全部三个选项(min、mid、max),那么对列表进行排序可能是最好的。一次比较和交换以获得前两个的顺序,然后最多进行两次测试以确定其他两个的顺序。是的,尽管这是一个特定的解决方案,而且此解决方案也可以在C中工作,而不像std::swapPTrue-虽然求中值(或n_最大值)的一般算法是基于快速排序的,但跳过了不必要的工作。@AlanStokes:当然,我同意。这个版本是为了可读性和可理解性而优化的,而那个版本是为了效率和灵活性而优化的。这里没有效率问题,OP似乎询问了三个值,但是,我认为这两个值都是有效的。但是,是的,排序对3个以上的元素也起着温和的作用;只需要确定奇数。@AlanStokes:更新了一个与C兼容的交换排序版本(即气泡排序),以防万一:这不是一种泡沫排序吗?@AbhishekBansal这确实是一种泡沫排序。@OliCharlesworth:我是知道的。我不想问这个:那又怎样?我不能说它在C语言中不起作用?你认为“只是说”是什么意思@LaszloPapp:只是不确定你之前评论的目的是什么,仅此而已(这段代码在Java中也不起作用!)。(例如,这很容易被视为对标签的误读。)@OliCharlesworth:“仅仅说”通常意味着这不是一件大事,而且此人知道具体情况。在谈论兼容性时,比较C++中的java和C是奇怪的,我必须这么说,尤其是考虑到我的答案表明了一小时前的意图。Fwiw,我甚至对答案(以及问题)投了更高的票,尽管我有另一个答案
    const double mid = std::max(std::min(x,y),std::min(std::max(x,y),z));
    
    template <typename T>
    const T& median(const T& a, const T& b, const T& c)
    {
        if (a < b)
            if (b < c)
                return b;
            else if (a < c)
                return c;
            else
                return a;
        else if (a < c)
            return a;
        else if (b < c)
            return c;
        else
            return b;
    }