Упрощение сравнений с помощью двоичной арифметики | IT Blog

Пусть у нас есть несколько условий, которые могут выполнятся одновременно. И есть несколько ветвей алгоритма, которые нужно выполнить в зависимости от результатов проверок.

Для примера рассмотрим такую задачу. Мы разрабатываем веб-приложение с графическим интерфейсом, в котором можно рисовать прямоугольники. Размер прямоугольника можно менять “потянув” за край или угол. Нужно, в зависимости от положения мыши относительно прямоугольника, изменить курсор мыши так, чтобы пользователю было понятно, как можно изменить размер прямоугольника.

Чтобы решить, какой из курсоров использовать, нужно выполнить 8 проверок (по числу возможных курсоров), в которых будут фигурировать 4 условия:

  1. Курсор около левой границы
  2. Курсор около верхней границы
  3. Курсор около правой границы
  4. Курсор около нижней границы

Всего эти 4 условия дают 16 возможных комбинаций.

Если записать результат вычисления каждого условия в виде отдельного бита - получим четырех битное число, с диапазоном значений от 0 до 15. Например, значение 12 в полученном числе будет означать, что выполнились условия 3 и 4.

Теперь все необходимые ветки алгоритма, можно сгруппировать в hash-таблицу. Ключем будет значение, для которого установленные биты соответствуют требуемым условием, а значением - нужная ветка (например ссылка на функцию).

Для нашего приложения функция на javascript, вычисляющая нужный стиль курсора может быть таким:

function getCursorType(mouse, boxpos, boxsize) {
    var conds = [
        mouse.x - boxpos.x,             // левая граница
        mouse.y - boxpos.y,             // верхняя граница
        mouse.x + boxsize.h - boxpos.x, // правая граница
        mouse.y + boxsize.w - boxpos.y  // нижняя граница
    ];
    var result = 0;
    for (var i = 0; i < conds.length; i++) {
        result |= (Math.abs(conds[i]) <= offset) << i;
    }
    var cursors = {
        1 : 'w-resize',
        2 : 'n-resize',
        3 : 'nw-resize',
        4 : 'e-resize',
        6 : 'ne-resize',
        8 : 's-resize',
        9 : 'sw-resize',
        12 : 'se-resize'
    };
    return cursors[result];
}

Такой подход имеет свои плюсы и минусы:

Плюсы: Для большого числа условий и комбинаций составить и поддерживать таблицу вариантов значительно проще, чем множество вложенных условий.

Минусы: Для получения численного представления выполненных условий требуется произвести вычисления их всех. В случае с операторами if вычисление условий будет происходить до первого успеха. С другой стороны,  в операторах if нередко одно и тоже условие будет вычисляться несколько раз.

Оставить комментарий