Разница между | и ||, или & и &&
Это два простых примера на 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