Ниже мой псевдо код.
function highest(i, j, k)
{
if(i > j && i > k)
{
return i;
}
else if (j > k)
{
return j;
}
else
{
return k;
}
}
Я думаю, что работы, но это - самый эффективный путь в C++?
Чтобы найти наибольшее, вам нужно просмотреть ровно 3 инт, не больше и не меньше. Вы ищете 6 с 3 сравнениями. Вы должны быть в состоянии сделать это в 3 и 2 сравнениях.
int ret = max(i,j);
ret = max(ret, k);
return ret;
Ваш текущий метод: http://ideone.com/JZEqZTlj (0.40s)
Решение Криса:
int ret = max(i,j);
ret = max(ret, k);
return ret;
http://ideone.com/hlnl7QZX (0.39s)
Решение Игнасио Васкеса-Абрамса:
result = i;
if (j > result)
result = j;
if (k > result)
result = k;
return result;
http://ideone.com/JKbtkgXi (0.40s)
И решение Чарльза Бретана:
return i > j? (i > k? i: k): (j > k? j: k);
http://ideone.com/kyl0SpUZ (0.40s)
Из этих тестов все решения занимают в пределах 3% времени на выполнение, как и остальные. Код, который вы пытаетесь оптимизировать, и так очень короткий. Даже если вам удастся выжать из него 1 инструкцию, это вряд ли будет иметь огромное значение для всей вашей программы (современные компиляторы могут уловить эту небольшую оптимизацию). Потратьте свое время в другом месте.
EDIT: Обновил тесты, оказалось, что до этого он все еще оптимизировал часть из них. Надеюсь, больше не оптимизирует.
Псевдокод:
result = i
if j > result:
result = j
if k > result:
result = k
return result
Для подобного вопроса, нет никакой замены знанию того, что делает ваш оптимизирующий компилятор и что доступно на оборудовании . Если ваш фундаментальный инструмент - это двоичное сравнение или двоичный максимум, два сравнения или два максимума необходимы и достаточны.
Я предпочитаю решение Игнасио:
result = i;
if (j > result)
result = j;
if (k > result)
result = k;
return result;
потому что на обычном современном оборудовании Intel компилятор обнаружит, что чрезвычайно легко выполнить всего два сравнения и две инструкции cmov
, которые создают меньшую нагрузку на I -кэш и меньшая нагрузка на предсказатель ветвлений, чем условные ветки. (Кроме того, код ясен и легко читается.) Если вы используете x86-64, компилятор даже сохранит все в регистрах.
Обратите внимание, что вам будет сложно встроить этот код в программу , где ваш выбор имеет значение ...
Мне нравится устранять условные переходы в качестве интеллектуального упражнения. Имеет ли это какое-либо измеримое влияние на производительность, я понятия не имею :)
#include <iostream>
#include <limits>
inline int max(int a, int b)
{
int difference = a - b;
int b_greater = difference >> std::numeric_limits<int>::digits;
return a - (difference & b_greater);
}
int max(int a, int b, int c)
{
return max(max(a, b), c);
}
int main()
{
std::cout << max(1, 2, 3) << std::endl;
std::cout << max(1, 3, 2) << std::endl;
std::cout << max(2, 1, 3) << std::endl;
std::cout << max(2, 3, 1) << std::endl;
std::cout << max(3, 1, 2) << std::endl;
std::cout << max(3, 2, 1) << std::endl;
}
Это перебирание битов просто для развлечения, cmov
решение, вероятно, намного быстрее.
Не уверен, что это наиболее эффективно или нет, но это может быть, и оно определенно короче :
int maximum = max( max(i, j), k);
Как насчет
return i > j? (i > k? i: k): (j > k? j: k);
двух сравнений, без использования временных переменных стека ...