обнаружить 4 перестановки 2 значений переменных в операторе переключения - PullRequest
3 голосов
/ 09 сентября 2011

У меня есть 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 ]

4 голосов
/ 09 сентября 2011

В 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/

3 голосов
/ 09 сентября 2011

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

псевдокод:

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 = ....

1 голос
/ 11 сентября 2011

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

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

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

Вы также можете делать вложенные if:более читабельно - особенно если число условий растет.

1 голос
/ 09 сентября 2011

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

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
}

И это может сработать для трехмерного случая:

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.

1 голос
/ 09 сентября 2011

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

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;
}

Я бы сказал, что это не поможет сделать код намного понятнее.

...