Получите среднее значение в С++
Рассмотрим три значения 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;
}