Разница между | и ||, или & и &&

Это два простых примера на C++, написанных на Dev-cpp C++ 5.4.2:

float a, b, c;

if (a | b  & a | c)
   printf("x = %.2f\tF = %.0f\n", x, F);
else
   printf("x = %.2f\tF = %.2f\n", x, F);

и этот код:

float a, b, c;

if (a || b  && a || c)
   printf("x = %.2f\tF = %.0f\n", x, F);
else
   printf("x = %.2f\tF = %.2f\n", x, F);

Может кто-нибудь сказать мою разницу между || > | а также & > &&, Второй код работает, но первый - нет. И компилятор выдает сообщение об ошибке:

[Ошибка] недопустимые операнды типов 'float' и 'float' для двоичного оператора '&'.

4 ответа

Решение

Операторы |, &, а также ~ действовать на отдельные биты параллельно. Их можно использовать только для целочисленных типов. a | b делает независимую операцию ИЛИ каждого бита a с соответствующим битом b чтобы генерировать этот бит результата.

Операторы ||, &&, а также ! действовать на каждый весь операнд как единый true/false значение. Можно использовать любой тип данных, который неявно преобразуется в bool, Многие типы данных, в том числе float неявно конвертировать в bool с подразумеваемым !=0 операция.

|| а также && также "короткое замыкание". Это означает, что всякий раз, когда значение результата может быть определено только первым операндом, второй не оценивается. Пример:

ptr && (*ptr==7) Если ptr равно нулю, результат ложен без риска сбоя сегмента путем разыменования нуля.

Вы можете сравнить это с (int)ptr & (*ptr), Игнорирование того факта, что это было бы странной операцией, даже если (int)ptr равны нулю, весь результат будет равен нулю, поэтому человек может подумать, что вам не нужен второй операнд в этом случае. Но программа, скорее всего, все равно вычислит оба.

Вы, кажется, путать с символами операторов. Эти символы фактически разделены на две разные категории, которые являются побитовыми операторами и логическими операторами. Хотя они используют одни и те же символы, вы должны рассматривать их как разные операторы. Таблицы истинности для обеих категорий похожи, но значения разные. Может быть, поэтому люди используют подобные символы для операторов.

побитовые операторы

~  // NOT
&  // AND
|  // OR
^  // XOR

Побитовые операторы будут рассматривать все свои операнды как двоичные числа и действовать в соответствии с побитовыми таблицами истинности для каждого бита операндов.

Bit-wise Truth Table

x   y   x&y x|y x^y
0   0   0   0   0
1   0   0   1   1
0   1   0   1   1
1   1   1   1   0

x   ~x
0   1
1   0

логические операторы

!   // Logical NOT (negation)
&&  // Logical AND (conjunction)
||  // Logical OR  (disjunction)

Логический оператор будет рассматривать все свои операнды как bools и действовать в соответствии с таблицами истинности оператора. Любое число, которое не равно 0 будет trueиначе будет false,

Logical Truth Table

x   y    x&&y   x||y
F   F    F      F
T   F    F      T
F   T    F      T
T   T    T      T

x   !x
F   T
T   F

Например:

int a = 10;  // a = 0000 .... 0000 1010  <-- a 32 bits integer
             // a is not zero -> true
int b = 7;   // b = 0000 .... 0000 0111  <-- a 32 bits integer
             // b is not zero -> true

Тогда для побитового оператора:

assert(a & b == 2);   // 2 = 0000 .... 0000 0010  <-- every bit will & separately

Для логического оператора:

assert(a && b == true);  // true && true -> true

Битовые операторы, которые | (ИЛИ ЖЕ), & (А ТАКЖЕ), ^ (XOR) и ~ (дополнить) делать то, что вы ожидаете от них: они выполняют вышеупомянутые операции над битами.
Что касается вашей проблемы компиляции, то здесь нет побитовых операций для чисел с плавающей запятой.

Логические операторы, которые являются || (ИЛИ ЖЕ), && (И и ! (НЕ) знаю только значения true а также false,
Выражение true если его значение не 0, это false если его значение равно 0,
Сначала логические операторы выполняют эту операцию. Затем они выполняют свою соответствующую операцию:

  • ||: true если хотя бы один операнд true
  • &&: true если оба операнда true
  • !: true если операнд false

Обратите внимание, что все логические операторы являются операторами короткого замыкания.

Побитовая операция не поддерживается для чисел с плавающей запятой

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

Проверьте здесь, как преобразовать число с плавающей точкой в ​​интегралы, https://www.cs.tut.fi/~jkorpela/round.html

Другие вопросы по тегам