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

Това са два прости примера на 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' към двоичен 'operator&'.


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++, но човек не го вижда, защото не са синтактично различни от целите числа. Като каза това, някои умни хора тръгнаха по този начин, напр. ° С#. Това не е очевидно дизайнерско решение IMO.   -  person luk32    schedule 28.12.2015


Отговори (4)


Операторите |, & и ~ действат паралелно на отделни битове. Те могат да се използват само върху цели числа. a | b извършва независима операция ИЛИ на всеки бит от a със съответния бит от b, за да генерира този бит от резултата.

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

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

ptr && (*ptr==7) Ако ptr е нула, резултатът е false без никакъв риск от грешка на сегмента чрез дерефериране на нула.

Можете да контрастирате това с (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)

Логическият оператор ще разглежда всичките си операнди като 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
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