Умовний XOR?


87

Як так, що C # не має умовного XOR оператора?

Приклад:

true  xor false = true
true  xor true  = false
false xor false = false

15
Як !=працює заміна?
Паскаль Куок,

45
C # робить мати XOR оператор (х ^ у). Тому я заперечую передумову питання. Чи можете ви пояснити, чому ви вважали, що C # не має оператора xor? Мені цікаво дізнатися, чому люди вірять у помилкові речі щодо C #.
Ерік Ліпперт,

3
@ Ерік Ліпперт: Я думаю, він має на увазі логічні оператори ( & | ^) проти умовних операторів ( && ||). Але ти маєш рацію (звичайно), є логічний XOR ...
BoltClock

14
@BoltClock: О, якщо питання "чому немає короткого замикання оператора xor?" - як це могло бути? За допомогою "і", якщо перший аргумент хибний, не потрібно оцінювати другий. За допомогою "або", якщо перший аргумент істинний, тоді вам не потрібно оцінювати другий. Завжди потрібно оцінювати обидва аргументи для xor, тому коротке замикання неможливе.
Eric Lippert

4
Саме це питання найкраще підходить для Microsoft - і тому це гідна причина, щоб проголосувати проти, але якщо той, хто проголосував за це, зробив це через оператор ^, то вам потрібно читати з більшою увагою до деталей, оскільки питання було умовним проти логічно, а не просто "чому немає XOR".
The Evil Greebo

Відповіді:


121

У C # умовні оператори виконують лише свій вторинний операнд, якщо це необхідно .

Оскільки XOR повинен за визначенням перевіряти обидва значення, умовна версія була б безглуздою.

Приклади :

  • Логічне І: &- щоразу тестує обидві сторони.

  • Логічне АБО: |- щоразу перевіряйте обидві сторони.

  • Умовне І: &&- перевіряє лише другу сторону, якщо перша сторона відповідає дійсності.

  • Умовне АБО: ||- протестуйте 2-ю сторону, лише якщо 1-ва сторона хибна.


35
Оператор XOR не буде порушувати конвенцію "умовні оператори лише виконують свій вторинний операнд, якщо це необхідно". Це завжди було б потрібно.
Натан Ковнер,

2
Умовний XOR може бути приємним та елегантним ярликом для деяких конкретних шаблонів, хоча не впевнений, чи достатньо виправданий, щоб включити його в мову. Прикладом таких шаблонів, де XOR може виявитись корисним, є умовне заперечення: коли логічний вираз потрібно заперечувати чи ні, отримуючи другий логічний вираз.
СальвадорГомес,

1
Деякий час не реагував на це, але відповідав на популярний коментар @KhyadHalda: Чому б ти коли-небудь будував те, що, як ти знаєш, ніколи не використовувалося? Ви навмисно писали б мертвий код.
The Evil Greebo

Враховуючи, що умовний оператор XOR не буде порушувати визначену вами конвенцію (коментар Хайада), разом із тим, що він насправді був би корисним, це майже заперечує будь-яку "безглуздість", яку ви приписуєте такому існуючому оператору.
Syndog

1
Як, коли-небудь, умовний XOR коли-небудь буде корисним? Умовний XOR ніколи не може оцінити, не порівнюючи обидві сторони, щоб визначити, що вони рівні чи ні. Навіть поняття умовного XOR, що порівнює два пули, все одно повинно перевіряти значення кожного буля і перевіряти рівність.
The Evil Greebo

280

Питання трохи застаріле, але ...

Ось як повинен працювати цей оператор:

true xor false = true
true xor true = false
false xor true = true
false xor false = false

Ось як працює оператор! = З типами bool:

(true != false) // true
(true != true) // false
(false != true) // true
(false != false) // false

Отже, як ви бачите, неіснуюче ^^можна замінити існуючим!=


46
Насправді це єдина відповідь, яка безпосередньо і правильно вирішує питання.
usr

39
Я сиджу тут обличчям до себе, що не підозрював, що це !=буде працювати.
AdamMc331

1
Відповідь правильна, але коментарі - ні. Він не стосується питання, а саме: "чому C # не має умовного XOR?". Строго кажучи, це не логічний оператор, це оператор реляційної рівності. Хоча результат такий самий, як XOR, він в іншому класі. Він порівнюється з XOR лише при тестуванні двох булевих значень, і обидві сторони оператора все одно повинні бути оцінені.
The Evil Greebo,

3
@TheEvilGreebo - те, що ти кажеш, є правдою; оператор! = технічно не є умовним оператором XOR. Однак ця відповідь фактично говорить: "Умовний оператор XOR не існує, оскільки існує оператор! =". Так я його читав, у будь-якому разі.
Syndog

6
Я думаю, що майже кожен, хто закінчив цю посаду, насправді хотів написати XOR на логічну форму. начебто логічно ANDі ORале нічого як XOR. або принаймні ми не усвідомлювали !=:) @TheEvilGreebo
M.kazem Akhgary

30

Існує логічний оператор XOR: ^

Документація: Оператори C # та ^ Оператор


2
Логічний, а не умовний. Логічні та = &, умовні та = &&. Він запитує про умовний.
The Evil Greebo

3
Це двійкове, не логічне. Він передбачає, що bools мають значення 0 або 1, що не відповідає дійсності в CLR.
usr

1
вибачте, ця відповідь насправді не відповідає на питання про УМОВНІ оператори. це трохи оператор
Натан Трегіллус

2
Щодо запису, у документації, на яку посилається ця відповідь, чітко зазначено, що ^при використанні з логічними операндами є логічним оператором. "для операндів bool оператор ^ обчислює той самий результат, що і оператор нерівності! =". Ви також можете розрядно-xor цілі операнди за допомогою ^. C # - це не C.
15ee8f99-57ff-4f92-890c-b56153

24

Як уточнення, оператор ^ працює як з інтегральними типами, так і з bool.

Див . ^ Оператор MSDN (посилання на C #) :

Двійкові ^ оператори визначені для інтегральних типів та bool. Для інтегральних типів ^ обчислює побітове виключення-АБО своїх операндів. Для bool-операндів ^ обчислює логічний ексклюзив або його операнди; тобто результат є істинним тоді і лише тоді, коли точно відповідає одному з його операндів.

Можливо, документація змінилася з 2011 року, коли було задано це питання.


2
давно програмував на c #, ніколи цього не знав! дякую @RichardCL!
Nathan Tregillus

Це гарна інформація, але видається більш доречним як коментар або редагування до іншої відповіді, яка згадує ^та передує цій відповіді на п’ять років. Сумніваюся, що-небудь змінилося.
Кріс

13

На запитання Марка Л , ось правильна версія:

 Func<bool, bool, bool> XOR = (X,Y) => ((!X) && Y) || (X && (!Y));

Ось таблиця правди:

 X | Y | Result
 ==============
 0 | 0 | 0
 1 | 0 | 1
 0 | 1 | 1
 1 | 1 | 0

Довідково: Ексклюзивно АБО


2
Задавалося запитання ЧОМУ C # не має умовного оператора XOR. Це не відповідає на питання. Щодо самої функції: ця функція дійсно працює як умовний XOR - однак питання полягає в тому, чи є вона більш ефективною, ніж безумовний XOR? Для того, щоб перевірити ексклюзивну істину, XOR повинен підтвердити, що один і точно один результат є істинним. Це означає, що обидві сторони повинні бути оцінені та порівняні. Функція, наведена вище, перевіряє обидві сторони an і умови, перетворюючи принаймні одне значення. Чи знаємо ми внутрішньо, чи це щось відрізняється від XOR?
The Evil Greebo

6

О так, це так.

bool b1 = true;
bool b2 = false;
bool XOR = b1 ^ b2;

1
Це двійковий оператор, а не логічний. Він передбачає, що bools мають значення 0 або 1, що не відповідає дійсності в CLR. Тож цей код насправді може не працювати.
usr

6
@usr, У C # оператор ^ логічний, якщо застосовується до двох булевих операндів. Ви надзвичайно багато коментували ці відповіді, чи запускали ви коли-небудь код для перевірки своєї гіпотези?
Marc L.

2
@MarcL. Я зробив: pastebin.com/U7vqpn6G Друкує true, хоча true ^ true вважається помилковим. bool не завжди дорівнює 0 або 1. Це не логічний тип в CLR. Це 8-бітна величина з довільним вмістом. Я міг створити перевіряється ІЛ, щоб також продемонструвати проблему.
usr

2
Наприклад, при використанні інших мов CLR, ніж C #. Повторюю: я міг використати ILASM для створення повністю перевіряється, безпечної збірки, яка робить це (на рівні IL булеве значення - це i1просто, як і байт). Це 100% визначена та безпечна керована поведінка. CLR не є грубим .; Вперше я побачив таку поведінку під час використання Microsoft Pex.
usr

1
@EdPlunkett, я не думаю, що твій вантажівка зі мною. usr показав, що всередині насправді це двійковий оператор. "Зловживання", на яке я скаржився, було засобом, яким він це довів, і я досі стверджую, що це занадто різко. Це може трапитися, але використання Boolean настільки ретельно ставиться до нічиєї землі, що його використання як безпечного для CLR було б у кращому випадку небезпечним, а в гіршому - жорстоким (якщо не шкідливим), і до нього слід ставитись як до помилки. Що доводить usr, це те, що внутрішньо C # більше схожий на C, ніж хтось із нас думав. Інше питання - чи слід вважати код, який це робить, дійсним.
Марк Л.

4

Умовний xor не існує, але ви можете використовувати логічний, оскільки xor визначено для логічних типів, а всі умовні порівняння оцінюються як логічні.

Тож ви можете сказати щось на зразок:

if ( (a == b) ^ (c == d))
{

}

Це двійковий оператор, а не логічний. Він передбачає, що bools мають значення 0 або 1, що не відповідає дійсності в CLR. Тож цей код насправді може не працювати.
usr

@usr що ти маєш на увазі CLR? Це спрацювало для мене, не впевнений, що я пропустив тут
крайній

3
@Spencevail, ви, мабуть, не замислювались про те, що неправдиве логічне значення може не мати цілочисельного подання 1. Це маловідомий факт. Ви можете опинитися в ситуації, коли xor двох неправдивих булевих символів все ще не хибний! Сказане в цьому конкретному коді оператор xor застосовується лише до значень у [0,1], тому мій коментар не застосовується (повністю).
usr

1
@Spencevail - це саме той випадок, який може провалитися. Можна створити безпечну керовану функцію коду CreateBool (байт), яка перетворює байт в бул тих самих бітів. Тоді CreateBool (1) ^ CreateBool (2) є істинним, але CreateBool (1) є істинним, а CreateBool (2) - також істинним! &також вразливий.
usr

1
Насправді, я щойно повідомив про помилку RyuJIT, оскільки вони не врахували таку можливість і зібрали &&так, ніби це було, &що є неправильною компіляцією.
usr

3

Хоча існує логічний оператор xor ^, умовного оператора xor не існує . Ви можете досягти умовного xor двох значень A і B, використовуючи наступне:

A ? (!B) : B

Парени не потрібні, але я додав їх для наочності.

Як вказує The Evil Greebo, це обчислює обидва вирази, але xor не може бути короткозамкненим, як і та або .


Яка різниця між логіканом ^ та умовним ^? оо
Армен Tsirunyan

@Armen Tsirunyan Логічні оператори виконують побітові операції у типах, де це має сенс, тоді як умовні оператори оперують логічними значеннями і повертають логічний результат. Враховуючи логічні значення: 0101 ^ 0011має значення 0110.
jimreed

3
ні, ви абсолютно помиляєтесь. є обидва типи XOR (вони називаються побітовими та логічними, відповідно) в C #. В обох використовується символ ^.
Армен Цирунян


0

Не існує такого поняття, як умовне (коротке замикання) XOR. Умовні оператори мають значення лише тоді, коли є спосіб остаточно визначити кінцевий результат, розглядаючи лише перший аргумент. XOR (і доповнення) завжди вимагає двох аргументів, тому після першого аргументу немає можливості короткого замикання.

Якщо ви знаєте A = true, то (A XOR B) =! B.

Якщо ви знаєте A = false, то (A XOR B) = B.

В обох випадках, якщо ви знаєте A, але не B, то знаєте недостатньо, щоб знати (A XOR B). Ви завжди повинні вивчити значення як A, так і B, щоб обчислити відповідь. Буквально не існує жодного випадку використання, коли ви коли-небудь можете вирішити XOR без обох значень.

Майте на увазі, XOR за визначенням має чотири випадки:

false xor true  = true
true  xor false = true
true  xor true  = false
false xor false = false

Знову ж таки, сподіваємось, з вищесказаного очевидно, що знання першого значення ніколи не буває достатнім для отримання відповіді, не знаючи також другого значення. Однак у своєму питанні ви пропустили перший випадок. Якщо ви натомість хотіли

false op true  = false (or DontCare)
true  op false = true
true  op true  = false
false op false = false

тоді ви дійсно можете отримати це за допомогою короткого замикання умовної операції:

A && !B

Але це не XOR.


У цій відповіді я не бачу нічого, що не було б принаймні в одній відповіді вище. Я не бачу жодних ознак того, що ваш короткозамкнений un-xor - це те, що шукав OP, оскільки він прийняв відповідь, яка передбачає, що він хотів належного xor.
15ee8f99-57ff-4f92-890c-b56153

Моя буквально єдина запропонована відповідь на даний момент, яка може створити запитувану ОП таблицю істинності без оцінки другого аргументу.
Кевін Холт,

Також ОП запитав, чому немає умовного XOR, і хоча відповіді, наведені вище, правильно говорять, що це тому, що XOR вимагає двох аргументів, IMO у відповідях вище, здається, недостатньо пояснює ЧОМУ XOR насправді потрібні два аргументи. Очевидно, ви відчуваєте інакше, але для мене було видно з різних коментарів на цій сторінці, що основна двоаргументовність XOR ще не була повністю роз'яснена абсолютно новачку.
Кевін Холт,

1
Ви намовили мене на це.
15ee8f99-57ff-4f92-890c-b56153

@Kevin Holt - Логічний XOR має значення, якщо вам потрібна одна з умов, щоб бути істинною, але не обидві. Те, що ви повинні оцінити обидві умови, не має значення. Річ із коротким замиканням - це деталь низького рівня, про яку вам слід турбуватися лише при роботі з критичним кодом продуктивності (потік управління повільний). Мене б більше цікавило, що має означати "ексклюзив" або "логічний оператор". А саме, нехай він працює як розрядна версія (як інші оператори), або зробіть це або що є ексклюзивним (скільки завгодно умов, але лише одне може бути істинним).
Торхем,

-3

На це запитання відповіли афективно, але я зіткнувся з іншою ситуацією. Це правда, що немає потреби в умовному XOR. Також вірно, що можна використовувати оператор ^. Однак, якщо вам потрібно протестувати лише статус "true || false" операндів, тоді ^ може призвести до проблем. Наприклад:

void Turn(int left, int right)
{
    if (left ^ right)
    {
        //success... turn the car left or right...
    }
    else
    {
        //error... no turn or both left AND right are set...
    }
}

У цьому прикладі, якщо зліва встановлено значення 10 (0xa), а праворуч встановлено значення 5 (0x5), вводиться гілка "успіху". У цьому (спрощеному, якщо дурному) прикладі це призведе до помилки, оскільки не слід одночасно повертати вліво та вправо. Що я довідався від запитувача, це не те, що він насправді хотів умовного, а простий спосіб виконати істинні / хибні значення для значень, переданих xor.

Макрос може зробити фокус:

#define my_xor(a, b) ( ((a)?1:0) ^ ((b)?1:0) )

Не соромтеся ляпати мене, якщо я не в курсі: o)

Відповідь jimreed я прочитав нижче після того, як опублікував це (поганий Yapdog!), А його насправді простіше. Це спрацювало б, і я абсолютно не уявляю, чому його відповідь була відхилена ...


3
Це питання на C #, а не на C / C ++. ifвимагає булевого виразу, він навіть не компілюється з int.
Марк Л.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.