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

Это два простых примера на 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' для двоичного 'оператора &'.


person Boris Veriga    schedule 28.12.2015    source источник
comment
en.wikipedia.org/wiki/Bitwise_operations_in_C   -  person JSF    schedule 28.12.2015
comment
Отсюда можно было бы получить некоторую отправную точку об указателях и операторах сравнения en.cppreference.com/ w / cpp / language / operator_comparison и cplusplus.com/doc/tutorial/pointers   -  person mkungla    schedule 28.12.2015
comment
Мне кажется странным, что C ++ не допускает побитовых операций с числами с плавающей запятой, хотя можно сказать, что они не имеют особого смысла, это все еще битовые последовательности, и с ними можно выполнять арифметические операции.   -  person Willem Van Onsem    schedule 28.12.2015
comment
@WillemVanOnsem По этой логике для поддержки бинарных операций им потребуется добавить новый тип, например. binary32, binary64 и т. Д. И набор функций преобразования. В C ++ они семантически различны, но этого не видно, потому что они синтаксически не отличаются от целых чисел. Сказав это, некоторые умные люди пошли этим путем, например. C #. ИМО это не очевидное дизайнерское решение.   -  person luk32    schedule 28.12.2015


Ответы (4)


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

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

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

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

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

person JSF    schedule 28.12.2015

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

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

~  // 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)

Логический оператор будет рассматривать все свои операнды как логические значения и действовать в соответствии с таблицами истинности оператора. Любое число, не равное 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
person Jaege    schedule 28.12.2015

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

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

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

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

person cadaniluk    schedule 28.12.2015

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

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

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

person Sazzad Hissain Khan    schedule 28.12.2015
comment
Всем большое спасибо! Ваши комментарии решили мою проблему =) - person Boris Veriga; 29.12.2015