обнаружение 4 перестановок 2 значений переменных в операторе switch case


У меня есть 2 переменные, width и height в виде целых чисел. Любой из них может быть положительным или отрицательным (не нулевым). Поэтому, естественно, есть 4 случая;

  1. width > 0 && height > 0
  2. width > 0 && height < 0
  3. width < 0 && height > 0
  4. width < 0 && height < 0
Теперь я хочу предпринять различные действия в каждом из этих 4 случаев, не используя 4 оператора if.

Есть ли способ объединить эти случаи так, чтобы он мог быть поставлен как простой switch case

switch( aggregate ){
  case 1:
  case 2:
  case 3:
  case 4:
}

Если нет лучшего способа, чем использовать if для каждый тогда в трехмерном пространстве у вас будет 3 длины (x,y,z) и будет 27 if блоков.

Я используюjavascript , если это имеет значение.

5 3

5 ответов:

В javascript это довольно просто, Просто переверните условие вверх ногами:

switch(true)
{
    case (width > 0 && height > 0):
        break;
    case (width > 0 && height < 0):
        break;
    case (width < 0 && height > 0):
        break;
    case (width < 0 && height < 0):
        break;

    default:

}

Это также работает в VB6/VBA, но не во многих других языках, таких как C++ и C#.

Вот простое доказательство: http://jsfiddle.net/avuxj/

Вы можете рассматривать каждое из ваших условий (ширина положительная, высота положительная) как один логический атрибут и объединить их в двоичное число и переключиться на него.

Псевдокод:

int v = (width > 0 ? 0 : 1) << 1 | (height > 0 ? 0 : 1) << 0;
switch (v) {
  case 0b00:
    // width < 0 && height < 0;
    break;
  case 0b01:
    // width < 0 && height > 0;
    break;
  case 0b10:
    // width > 0 && height < 0
    break;
  case 0b11:
    // width > 0 && height > 0
    break;
}

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

Также обратите внимание, что языки, которые поддерживают интерпретацию true как 1 и false как 0, помогут сделать строку int v = ... короче.

Вы могли бы сделать

var bits=0;
if(width > 0) {
     bits+=1;
}
if(height > 0) {
     bits+=2;
}

switch{bits} {
    case 0: //both negative
        //something
        break;
    case 1: //width positive, height negative
        //something
        break;
    case 2: //width negative, height positive
        //something
        break;
    case 3: //both positive
        //something
        break;
}
Хотя все это немного сбивает с толку. (Особенно если у вас есть 3 значения). Вы можете использовать переменные, чтобы сделать ваш код немного понятнее.
var WIDTH_POSITIVE_BIT=1;
var HEIGHT_POSITIVE_BIT=2;

var bits=0;
if(width > 0) {
     bits+=WIDTH_POSITIVE_BIT;
}
if(height > 0) {
     bits+=HEIGHT_POSITIVE_BIT;
}

switch{bits} {
    case 0: //both negative
        //something
        break;
    case WIDTH_POSITIVE_BIT: //width positive, height negative
        //something
        break;
    case HEIGHT_POSITIVE_BIT: //width negative, height positive
        //something
        break;
    case WIDTH_POSITIVE_BIT+HEIGHT_POSITIVE_BIT: //both positive
        //something
        break;
}
Я бы сказал, что это не помогает сделать код намного яснее.

Не могу сделать это, не добавив немного накладных расходов.

s = ( width < 0 ) ? 0 : 1;
s += ( height < 0 ) ? 0 : 2;

switch(s) {
    case  0: // 00 => both < 0
    case  1: // 01 => width > 0, height < 0
    case  2: // 10 => width < 0, height > 0
    case  3: // 11 => both > 0
}

И это может работать для 3D-случая:

s = ( width < 0 ) ? 0 : 1;   //First bit for width
s += ( height < 0 ) ? 0 : 2; //Second bit for height
s += ( depth < 0 ) ? 0 : 4;  //Third bit for depth

switch(s) {
    case  0: // 0 0 0
    case  1: // 0 0 1
    case  2: // 0 1 0
    case  3: // 0 1 1
    case  4: // 1 0 0
    case  5: // 1 0 1
    case  6: // 1 1 0
    case  7: // 1 1 1
}

Конечно, предполагая, что у вас не может быть измерения 0.

Несколько ответов являются логически правильными. Если бы вы делали это в C, это было бы:

s = ((width<0)<<1) | (height<0);
switch(s) {
....
}

Это может сделать огромную разницу. У меня есть код, который объединяет 9 условий в такой переключатель. Переключатель превращается в таблицу переходов и работает намного быстрее, чем оценка множества условий. Там нет ветвления, только таблица прыжков. Хотя я не могу говорить ни с чем java или Java script.

Вы также можете сделать вложенные операторы if:

if (witdh<0) {
    if (height<0) {
        // both negative
    }
    else {
        // only width negative
    }
 }
 else {
    if (height<0) {
        // only height negative
    }
    else {
        // both positive
    }
 }

Я нахожу, что растирание биты условий вместе и с помощью переключателя, чтобы быть более читаемым - особенно если число условий растет.