поведение bool с небулевыми операторами

Необходимо проверить на AI (Искусственный интеллект) книги. Я имею, узнают о Байесовском в Искусственный интеллект "Современный подход ".

6
задан deft_code 18 August 2009 в 16:59
поделиться

8 ответов

Согласно 4.7 (Интегральные преобразования), параграф 4 , "Если тип назначения - bool , см. 4.12. Если тип источника - bool , значение false преобразуется в ноль, а значение true преобразуется в единицу ". В версии 4.12 «r-значение арифметики, перечисления, указателя или указателя на тип элемента может быть преобразовано в r-значение типа bool . Нулевое значение, значение нулевого указателя, или значение указателя нулевого члена преобразуется в false ; любое другое значение преобразуется в true . "

В контексте, где операнды bool не разрешены, а целочисленные операнды разрешены, bool будет преобразовано в целочисленный тип. Когда целочисленный результат сохраняется в переменной bool , он будет преобразован в bool .

Таким образом, вы сможете использовать + и * как логические или and and, и вы можете использовать | и также. Вы не можете избежать их смешивания, поскольку (bool1 + bool2) & bool3 выдаст false , если все три переменные true . ((1 + 1) & 1 равно 2 & 1, что равно 0 или ложь.)

Помните, что | и || не работают одинаково даже здесь. | Будет оценивать обе стороны, а затем оцените побитовое или. || оценит первый операнд, тогда только если это было ложно, оценит второй.

Я не собираюсь обсуждать здесь стилистические проблемы, но если бы я сделал что-то подобное, я обязательно прокомментировал бы это, чтобы люди знали что я делал и почему.

13
ответ дан 8 December 2019 в 13:01
поделиться

Стандартный говорит:

4.5-4 «Интегральные продвижения»

Значение типа bool может быть преобразовано в rvalue типа int, с ложным становится нулевым и истинным становится единым.

5.17-7 «Операторы присваивания»

Поведение выражения форма E1 op = E2 эквивалентна E1 = E1 op E2, за исключением того, что E1 оценивается только однажды. В + = и - = E1 должен либо иметь арифметический тип, либо быть указатель на возможно cvqualified полностью определенный тип объекта. В целом в других случаях E1 должен иметь арифметические тип.

4.12-1 "Булевы преобразования"

Значение r арифметики, перечисления, указатель или указатель на тип элемента может быть преобразованным в rvalue типа булево. Нулевое значение, нулевой указатель значение или значение указателя нулевого члена преобразован в ложь; любое другое значение преобразовано в истину.

Таким образом, это означает, что

b1 += b2

Где b1 и b2 являются логическими, будет эквивалентно

b1 = b1 + b2

И b1 и b2 будут преобразованы в целые числа 0/1, а затем преобразованы обратно в логические по правилу, что истинно все, кроме 0.

Таким образом, таблица истинности

            true   false
true     true   true
false    true   false

, так что + = действительно работает как || = согласно стандарту. Однако это, вероятно, запутает других программистов, поэтому я бы все равно этого избегал.

4
ответ дан 8 December 2019 в 13:01
поделиться

Не могли бы вы просто использовать тернарный оператор?

old_value =! Old_value? possible_new_value: old_value;

1
ответ дан 8 December 2019 в 13:01
поделиться

Не используйте | = и & = с bools. Они могут работать большую часть времени, но это все равно неправильно. Обычно тип bool - это просто прославленный int или char. В более старом коде, с которым я работал, BOOL просто определяется типом int или char. В этих случаях вы можете получить неправильный ответ, если каким-то образом были изменены биты (например, 1 & 2 равно 0 (ложь)). И я не уверен, но я думаю, что результат побитовых операторов будет int, даже для bools.

0
ответ дан 8 December 2019 в 13:01
поделиться

Одно отличие состоит в том, что логические операторы, такие как || , гарантируют порядок вычисления и обеспечивают сокращение, в отличие от побитовых и арифметических операторов.

Я считаю, что компилятор будет обрабатывать нелогические операторы путем преобразования bools в числовые значения (0, 1), применяя оператор и конвертируя обратно. Эти преобразования строго определены стандартом, например:

r-значение арифметики, перечисления, указателя или указателя на тип элемента может быть преобразовано в r-значение типа bool. Нулевое значение, значение нулевого указателя или значение указателя нулевого члена преобразуются в ложь, любое другое значение преобразуется в истину.

0
ответ дан 8 December 2019 в 13:01
поделиться
if (!old_value)
    old_value = possible_new_value;

Это прямой эквивалент исходного состояния. Он мог бы генерировать более простой код, поскольку он не всегда будет присваиваться old_value - но я не ожидал бы, что разницу в производительности будет легко измерить в большой программе.

0
ответ дан 8 December 2019 в 13:01
поделиться

Я считаю, что стандарт явно определяет истину и ложь как 1 и 0, поэтому вы можете безопасно использовать побитовые операторы для значений bool . Другие типы, которые могут неявно обрабатываться как bools в другом контексте, должны быть явно преобразованы, чтобы это работало надежно.

Я видел, как компилятор Microsoft генерирует уродливое предупреждение каждый раз, когда вы делаете это, потому что он думает, что существует опасность неявного преобразования результат int возвращается в bool.

0
ответ дан 8 December 2019 в 13:01
поделиться

Грязное взлом макросов:

#define UPDATE(x) x = x

UPDATE(old_value) || possible_new_value;

Но я не рекомендую это вообще. Подобные макросы - очень плохая идея по нескольким причинам.

Более нормальная функция, но без короткого замыкания:

bool set_or(bool &old, bool value) {
  return (old = old || value);
}

...

bool v = false;
set_or(v, true);
0
ответ дан 8 December 2019 в 13:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: