Получите среднее значение в С++

Рассмотрим три значения x, y, z.

Какова будет формула, чтобы получить среднее значение (а не среднее значение, но значение, которое не является ни min, ни max)?

const double min = std::min(x, std::min(y, z));
const double mid = /* what formula here ? */
const double max = std::max(x, std::max(y, z));

Ответ 1

Ответ от этой ссылки поделился в комментариях:

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 оба (as отношение становится: max (x, y) > min (x, y) > z). Поэтому min (x, y) действительно является медианом, а max(min(x,y),z) возвращает это.
    Если min (x, y) < z, то z действительно является медианным (как min (x, y) < m < max (x, y)).

  • Если он возвращает x, то мы имеем x < z и y < г. Выражения оцениваются следующим образом: max(min(x,y),x). Так как max (x, y), вычисляемое на x, min (x, y), вычисляется на y. Получая отношение z > x > y. Мы возвращаем max x и y (поскольку выражение становится max(y,x)), которое является x, а также медианным. (Заметим, что доказательство для y симметрично)

Доказательства конца


Old Proof - Заметьте, что он НЕ завершен (прямой):

Не теряя общий смысл: Предположим, что x > y > z Min of x и y - y. И min of (max x и y) и z равно z.
Максимум y и z является y, который является медианным.

Предположим, что x = y > z Min of x и y say - x. И min of (max x и y равно x), а z - z.
Макс двух выше, х, который является медианным.

Предположим, что x > y = z Min of x и y - y. И min of (max x и y равно x), а z - z.
Макс двух указанных выше равен y, который является медианным.

Наконец, предположим, что x = y = z Любое из трех чисел будет медианным., И используемая формула вернет некоторое число.

Ответ 2

Чтобы найти все три одновременно симметрично:

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);

Ответ 3

Это похоже на обман, но: x + y + z - min - max

Ответ 4

Это немного уродливее, чем трюк Алана, но он не может вызвать переполнение, числовые ошибки и т.д.:

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;

Алгоритм выглядит следующим образом:

  • проверить, существует ли x между y и z, если да, то есть.

  • проверьте, находится ли y между x и z, если да, то есть.

  • Он должен быть z, так как он не был ни x, ни y.

=============================================== ======

Вы также можете получить это более гибко, если у вас есть более трех элементов, с сортировкой.

//или реализация xor, не имеет значения...

void myswap (int * a, int * b)  {      int temp = * b;      * b = * a;      * a = temp;   }

int x, y, z;
// Initialize them
int min = x;
int med = y;
int max = z;

// you could also use std::swap here if it does not have to be C compatible
// In that case, you could just pass the variables without the address operator.
if (min > med) myswap(&min, &med);
if (med > max) myswap(&med, &max);
if (min > med) myswap(&min, &med);

Ответ 5

Вариант аланового "чита", который (вроде и иногда) предотвращает переполнение:

#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;
}

Вывод:

6e+306

Используется avg-формула, часто используемая в двоичном поиске для предотвращения переполнения:

Среднее значение двух значений можно рассчитать как low + (high-low)/2

Однако он работает только для положительных значений. Возможные резервные копии включают ответ Алана или просто (x+y)/2 для вычисления avg.

Обратите внимание, что двойная точность вступает в игру здесь и может вызвать проблемы в mid -калькуляции. Он отлично работает для целых положительных чисел:)

Ответ 6

Лучший способ сделать это - создать общий шаблон медианы. Операции копирования, подкачки или математические операции не требуются.

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;
}