Это сложно, конечно.Учитывая, что вы хотите:
a b c rslt
0 0 0 0
0 0 1 1
0 1 0 1
0 1 1 0
1 0 0 1
1 0 1 0
1 1 0 0
1 1 1 0
Это сделает это:
rslt = (!a & (b ^ c)) || (a & !(b | c));
Первая часть обрабатывает четыре случая, где a
равен 0. Вторая часть, где a
не 0.
Более простой способ взглянуть на это так:
rslt = (a | b | c) & !((a & b) | (a & c) | (b & c))
То есть, одно из трех должно быть истинным, но никакие два (или более) не могут быть истинными.
Кажется, должен быть способ еще больше упростить, но это не приходит в голову.Может быть, мне нужно больше кофеина.
РЕДАКТИРОВАТЬ
Я думаю, что это то решение, которое я искал сегодня утром:
rslt = a ? !(b | c) : (b ^ c);
Теперь,что касается того, почему я использовал |
вместо ||
:
Это сочетание проблемы стиля и старого уклона против ветвления (старые привычки сильно умирают).!(b | c)
генерирует этот код IL:
ldarg.1
ldarg.2
or
ldc.i4.0
ceq
stloc.0
В этом коде нет ветвей.Если я использую ||
, как в !(b ||c)
, он генерирует:
ldarg.1
brfalse.s IL_009B
ldarg.2
br.s IL_009C
IL_009B:
ldc.i4.1
IL_009C:
stloc.0
, который имеет две ветви.Я не знаю, отразит ли это код, созданный JIT, но я подозреваю, что так и будет.Таким образом, один бит кода - это 6 инструкций, которые всегда выполняются.Другой 6 инструкций, из которых иногда только 4 выполняются.Но штрафы за ветвление вполне могут съесть любую выгоду от невыполнения двух инструкций.
Я понимаю, что современные процессоры намного лучше в ветвлении, чем 8086, и не может быть никакой заметной разницы во времени выполненияиз этих двух фрагментов кода.Даже если бы они были, маловероятно, что это могло бы существенно повлиять на общее время выполнения программ, которые я обычно пишу.
Но я говорю вам, что это, безусловно, раньше!На 8086, где ветвление было очень дорогим, разница между (b | c)
и (b || c)
составляла огромная .
Наконец, использование |
, как вы заметили, заставляет оцениватьвсе выражение.Мой оригинальный код говорит, по сути, «если это выражение истинно или , то это выражение истинно ».Использование &&
и ||
превращает его в набор условных выражений и, на мой взгляд, труднее читать.
Итак: старое предубеждение, основанное на наиболее вероятных устаревших соображениях производительности.Но безвреден.
Однако нужно быть осторожным, чтобы не писать что-то вроде (b() | c())
, если обе функции не должны быть оценены.