Самый эффективный способ найти самый большой из трех ints

Ниже мой псевдо код.

function highest(i, j, k)
{
  if(i > j && i > k)
  {
    return i;
  }
  else if (j > k)
  {
    return j;
  }
  else
  {
    return k;
  }
}

Я думаю, что работы, но это - самый эффективный путь в C++?

11
задан jww 22 July 2017 в 14:08
поделиться

7 ответов

Чтобы найти наибольшее, вам нужно просмотреть ровно 3 инт, не больше и не меньше. Вы ищете 6 с 3 сравнениями. Вы должны быть в состоянии сделать это в 3 и 2 сравнениях.

int ret = max(i,j);
ret = max(ret, k);
return ret;
26
ответ дан 3 December 2019 в 00:41
поделиться

Ваш текущий метод: 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: Обновил тесты, оказалось, что до этого он все еще оптимизировал часть из них. Надеюсь, больше не оптимизирует.

7
ответ дан 3 December 2019 в 00:41
поделиться

Псевдокод:

result = i
if j > result:
  result = j
if k > result:
  result = k
return result
14
ответ дан 3 December 2019 в 00:41
поделиться

Для подобного вопроса, нет никакой замены знанию того, что делает ваш оптимизирующий компилятор и что доступно на оборудовании . Если ваш фундаментальный инструмент - это двоичное сравнение или двоичный максимум, два сравнения или два максимума необходимы и достаточны.

Я предпочитаю решение Игнасио:

result = i;
if (j > result)
  result = j;
if (k > result)
  result = k;
return result;

потому что на обычном современном оборудовании Intel компилятор обнаружит, что чрезвычайно легко выполнить всего два сравнения и две инструкции cmov , которые создают меньшую нагрузку на I -кэш и меньшая нагрузка на предсказатель ветвлений, чем условные ветки. (Кроме того, код ясен и легко читается.) Если вы используете x86-64, компилятор даже сохранит все в регистрах.

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

5
ответ дан 3 December 2019 в 00:41
поделиться

Мне нравится устранять условные переходы в качестве интеллектуального упражнения. Имеет ли это какое-либо измеримое влияние на производительность, я понятия не имею :)

#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 решение, вероятно, намного быстрее.

4
ответ дан 3 December 2019 в 00:41
поделиться

Не уверен, что это наиболее эффективно или нет, но это может быть, и оно определенно короче :

int maximum = max( max(i, j), k);
3
ответ дан 3 December 2019 в 00:41
поделиться

Как насчет

return i > j? (i > k? i: k): (j > k? j: k);

двух сравнений, без использования временных переменных стека ...

13
ответ дан 3 December 2019 в 00:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: