Найти максимум 9 номеров - быстро

1

У меня 9 случайных целых чисел. Есть ли более быстрый способ найти максимум без явного сравнения всего?

Я выполняю эту операцию milion раз за кадр, и это довольно медленно.

function calculateMax(a, b, c, 
                      d, e, f,
                      g, h, i){
    var max = (a > b) ? a : b;
    var max2 = (c > d) ? c : d;
    var max3 = (e > f) ? e : f;
    var max4 = (g > h) ? g : h;

    max = (i > max) ? i : max;
    max = (max2 > max) ? max2 : max;
    max = (max3 > max) ? max3 : max;
    max = (max4 > max) ? max4 : max;

    return max;
}
  • 0
    Я не думаю, что вы можете найти максимум с меньшим, чем O(n) как вам нужно проверить каждое значение, сказать максимальное число
  • 0
    Невозможно найти наибольшее число из n чисел без n-1 сравнений и до n-1 назначений. Ваше узкое место - JavaScript. ЮК.
Показать ещё 7 комментариев
Теги:

2 ответа

2
Лучший ответ

Результаты кажутся довольно разочаровывающими после нескольких запусков, но публикуются в случае, если кто-то хочет сделать лучше тест на других браузерах или улучшить (может быть, быстрее с инструкциями SIMD)

function max1(a, b, c, d, e, f, g, h, i) {                   // shortened calculateMax
    var max  = (a > b) ? a : b; var max2 = (c > d) ? c : d;
    var max3 = (e > f) ? e : f; var max4 = (g > h) ? g : h;

    max = ( i   > max) ?  i   : max; max = (max2 > max) ? max2 : max;
    max = (max3 > max) ? max3 : max; max = (max4 > max) ? max4 : max;
    return max;
}

function max2(a, b, c, d, e, f, g, h, i) {
  if (a < b) a = b; if (a < c) a = c; if (a < d) a = d; if (a < e) a = e;
  if (a < f) a = f; if (a < g) a = g; if (a < h) a = h; if (a < i) a = i;
  return a;
}

//function max(a, b) { return a - ((a -= b) & (a >> 31 )); }
//function max(a, b) { return (a - b >>> 31) * b | (b - a >>> 31) * a }
function max(a, b) { return (a - b >> 31) & b | (b - a >> 31) & a }

function max3(a, b, c, d, e, f, g, h, i) {  
  return max(a, max(b, max(c, max(d, max(e, max(f, max(g, max(h, i))))))))
}

function max4(a, b, c, d, e, f, g, h, i) {
  a  =   (a - b >> 31) & b | (b - a >> 31) & a
  a  =   (a - c >> 31) & c | (c - a >> 31) & a
  a  =   (a - d >> 31) & d | (d - a >> 31) & a
  a  =   (a - e >> 31) & e | (e - a >> 31) & a
  a  =   (a - f >> 31) & f | (f - a >> 31) & a
  a  =   (a - g >> 31) & g | (g - a >> 31) & a
  a  =   (a - h >> 31) & h | (h - a >> 31) & a
  return (a - i >> 31) & i | (i - a >> 31) & a
}

var l = console.log, p = performance
var t = p.now(), m = max1(1,2,3,4,5,6,7,8,9); t -= p.now(); l(m, 1, -t)
var t = p.now(), m = max2(1,2,3,4,5,6,7,8,9); t -= p.now(); l(m, 2, -t)
var t = p.now(), m = max3(1,2,3,4,5,6,7,8,9); t -= p.now(); l(m, 3, -t)
var t = p.now(), m = max4(1,2,3,4,5,6,7,8,9); t -= p.now(); l(m, 4, -t)
  • 0
    К сожалению, тест производительности, который вы связали, мало что говорит нам об ожидаемой производительности при различных входных данных. Поскольку аргументы функций в этих тестах являются постоянными литеральными значениями, движок JavaScript будет оптимизировать их гораздо агрессивнее, чем в реальном сценарии.
2

Лучший способ - использовать встроенную реализацию:

Array.max = function( array ){
    return Math.max.apply( Math, array );
};

console.log(Array.max([1,2,9,8,3,2,1,2,5]));  // 9

cf: https://johnresig.com/blog/fast-javascript-maxmin/

  • 0
    Всегда стоит проверять эти вещи. Даже если вы избежите ненужного создания массива, описанного выше, в Chrome и IE11 прямое использование Math.max медленнее, чем функции OP. (Это заметно быстрее в Firefox, но не в том случае, если вы добавляете в создание массивов и такие, как у вас выше.)
  • 0
    @TJCrowder Интересно, что преимущество встроенного в Firefox Math.max исчезает, когда мы больше не поддерживаем постоянные входные данные. Оптимизирует ли IonMonkey в Firefox такие «постоянные» вызовы встроенных функций?
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню