Упростить, если условие логическое выражение

У меня есть это if-condition в моем коде:

if (a||a&&!b){
// do some stuff
}

с этими начальными значениями из моего junit test:

boolean a=true, b = true;

как я понял позже, утверждение можно упростить до:

if (a&&b)

становится зеленым: Assert.assertTrue(a||a&&!b == a&&b);

Есть ли еще какие-то упрощения? Как я мог понять, что это логическое выражение можно упростить?


person s_bei    schedule 05.03.2014    source источник
comment
a || a && !b не равно a && b. Он равен всего a.   -  person Marko Topolnik    schedule 05.03.2014
comment
Я настоятельно рекомендую использовать пробелы, чтобы ваш код было легче читать... и круглые скобки, где может потребоваться некоторое время для определения приоритета, также могут помочь.   -  person Jon Skeet    schedule 05.03.2014
comment
Wolfram Alpha на самом деле упрощает булеву алгебру. Может потребоваться некоторое преобразование ответа, который он дает вам, чтобы сделать его совместимым с вашим языком программирования, но концепция работает и отлично себя зарекомендовала. Вот ссылка на страницу   -  person WearyWanderer    schedule 05.03.2014
comment
Булева алгебра позволяет упростить логические выражения.   -  person Tom Verelst    schedule 05.03.2014
comment
Да. Булева алгебра существует для упрощения.   -  person user3256147    schedule 05.03.2014
comment
Вы можете использовать карту Karnaugh для упрощения логической логики. С 3 или более переменными - лучший способ   -  person Manuel Spigolon    schedule 05.03.2014
comment
@Marko Topolnik: этот тест становится зеленым Assert.assertTrue(a||a&&!b == a&&b);   -  person s_bei    schedule 05.03.2014
comment
Я знаю, что булева алгебра делает это. Я написал приложение для Android, чтобы шаг за шагом упростить логические выражения :) К сожалению, в моем приложении есть одна ошибка, которую я не узнаю в приведенном выше случае...   -  person s_bei    schedule 05.03.2014
comment
@StefanBeike То, что вы использовали определенную комбинацию значений для a и b, где результаты совпадают, не означает, что выражения эквивалентны. Это не так.   -  person Marko Topolnik    schedule 05.03.2014


Ответы (3)


a || a && !b 

не равно

a && b

Он равен всего a.

Я предполагаю, что в вашем тесте JUnit вы использовали определенную комбинацию значений для a и b, при которой результаты совпадают, но это не означает, что выражения эквивалентны, а на самом деле это не так. Быстрый способ убедиться в этом — проверить комбинацию

a = true, b = false;

Ваше исходное выражение явно дает true для всех случаев, где a == true, но ваше второе выражение будет давать false всякий раз, когда b == false.

Что касается формального доказательства эквивалентности просто a, возьмите расширение

a == a && (b || !b)
  == a && b || a && !b

Подключение к исходному выражению:

a || a && !b == a && b || a && !b || a && !b
             == a && b || a && !b
             == a
person Marko Topolnik    schedule 05.03.2014

Просто проверьте таблицу истинности (я добавил скобки)

  a || (a && (!b))

  a|b|result
  ----------
  T|T|T 
  T|F|T 
  F|T|F 
  F|F|F

Как мы видим, формула не зависит от b и может быть упрощена до

  a

Окончательно

  if (a) {
    // do some stuff
  }

Для формул с многими переменными, когда таблица истинности слишком длинная для ручного анализа, вы можете использовать карты Карно, как предложил Эомм.

person Dmitry Bychenko    schedule 05.03.2014
comment
Если вы правы, мое приложение работает правильно. Это упрощается с одним шагом (поглощение) - person s_bei; 05.03.2014

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

Карта Карно для вашего выражения очень проста - она ​​выглядит так:

введите здесь описание изображения

Это упрощается до a, а не a && b.

person Sergey Kalinichenko    schedule 05.03.2014