4.9 – Логические (булевы) значения
В реальной жизни часто задаются вопросы, на которые можно ответить «да» или «нет». «Яблоко – это фрукт?». Да. «Тебе нравится спаржа?». Нет.
Теперь рассмотрим аналогичное утверждение, на которое можно ответить «верно/истина» (true) или «неверно/ложь» (false): «Яблоки – это фрукты». Совершенно очевидно, что это истина. Или как насчет «Я люблю спаржу». Абсолютно неверно (фу!).
Такие предложения, которые имеют только два возможных результата: да/истина или нет/ложь, настолько распространены, что многие языки программирования включают в себя специальный тип данных для работы с ними. Этот тип называется логическим (булевым, Boolean) типом (примечание: Boolean на английском правильно пишется с заглавной буквы, потому что этот тип назван в честь своего изобретателя Джорджа Буля).
Логические переменные
Логические переменные – это переменные, которые могут иметь только два возможных значения: true (истина) и false (ложь).
Чтобы объявить логическую переменную, мы используем ключевое слово bool.
bool b;
Чтобы инициализировать или присвоить логической переменной значение истина или ложь, мы используем ключевые слова true и false.
bool b1 { true };
bool b2 { false };
b1 = false;
bool b3 {}; // по умолчанию инициализируется значением false
Так же, как унарный оператор минус (-) может использоваться для превращения положительного числа в отрицательное, логический оператор НЕ (!) Может использоваться для переключения логического значения с true на false или с false на true:
bool b1 { !true }; // b1 будет инициализирована значением false
bool b2 { !false }; // b2 будет инициализирована значением true
Логические значения на самом деле не хранятся в логических переменных в виде слов «true» или «false». Вместо этого они хранятся как целые числа: true становится целым числом 1, а false становится целым числом 0. Аналогично, когда вычисляются логические значения, они на самом деле не оцениваются как «true» или «false». Они оценивают целые числа 0 (false) или 1 (true). Поскольку логические значения фактически хранят целые числа, они считаются целочисленным типом.
Печать логических переменных
Когда с помощью std::cout мы печатаем логические значения, std::cout печатает 0 для false и 1 для true:
#include <iostream>
int main()
{
std::cout << true << '\n'; // true вычисляется как 1
std::cout << !true << '\n'; // !true вычисляется как 0
bool b{false};
std::cout << b << '\n'; // b равно false, которая вычисляется как 0
std::cout << !b << '\n'; // !b равно true, которая вычисляется как 1
return 0;
}
Вывод этой программы:
1
0
0
1
Если вы хотите, чтобы std::cout выводил «true» или «false» вместо 0 или 1, вы можете использовать std::boolalpha. Например:
#include <iostream>
int main()
{
std::cout << true << '\n';
std::cout << false << '\n';
std::cout << std::boolalpha; // выводим логические переменные как true или false
std::cout << true << '\n';
std::cout << false << '\n';
return 0;
}
Эта программа напечатает:
1
0
true
false
Чтобы отключить этот способ вывода, вы можете использовать std::noboolalpha.
Преобразование целочисленных значений в логические
Вы не можете инициализировать логическое значение целым числом, используя унифицированную инициализацию:
#include <iostream>
int main()
{
bool b{ 4 }; // ошибка: сужающее преобразование запрещено
std::cout << b;
return 0;
}
(примечание: некоторые версии g++ не обеспечивают генерирование этой ошибки)
Однако в любом контексте, где целочисленное значение может быть преобразовано в логическое значение, целое число 0 преобразуется в false, а любое другое целое число преобразуется в true.
#include <iostream>
int main()
{
std::cout << std::boolalpha; // выводим логические значения как true или false
bool b1 = 4; // копирующая инициализация допускает неявное преобразование int в bool
std::cout << b1 << '\n';
bool b2 = 0; // копирующая инициализация допускает неявное преобразование int в bool
std::cout << b2 << '\n';
return 0;
}
Эта программа напечатает:
true
false
Ввод логических значений
Ввод логических значений с помощью std::cin начинающих программистов иногда сбивает с толку.
Рассмотрим следующую программу:
#include <iostream>
int main()
{
bool b{}; // по умолчанию инициализируется значением false
std::cout << "Enter a boolean value: ";
std::cin >> b;
std::cout << "You entered: " << b << '\n';
return 0;
}
Enter a Boolean value: true
You entered: 0
Погодите, что?
Оказывается, std::cin принимает для логических переменных только два входных значения: 0 и 1 (а не true или false). Любые другие входные данные вызовут молчаливый сбой std::cin. В этом случае, поскольку мы ввели true, std::cin молча завершился ошибкой. Неудачный ввод также обнулит переменную, поэтому b также получит значение false. Следовательно, когда std::cout печатает значение b, он печатает 0.
Чтобы заставить std::cin принимать в качестве входных данных «false» и «true», необходимо включить параметр std::boolalpha.
#include <iostream>
int main()
{
bool b{};
std::cout << "Enter a boolean value: ";
// бработка "false" и "true" как логических значений
std::cin >> std::boolalpha;
std::cin >> b;
std::cout << "You entered: " << b << '\n';
return 0;
}
Однако, когда включен std::boolalpha, «0» и «1» больше не будут обрабатываться как логические значения.
Логические возвращаемые значения
Логические значения часто используются в качестве возвращаемых значений для функций, которые проверяют, является ли что-то истинным или нет. Такие функции обычно называются, начиная со слова is (т.е. «является», например, isEqual) или has (т.е. «имеет», например, hasCommonDivisor).
Рассмотрим следующий пример, очень похожий на приведенный выше:
#include <iostream>
// возвращает true, если x и y равны, иначе false
bool isEqual(int x, int y)
{
// operator== returns возвращает true, если x равно y, и false в противном случае
return (x == y);
}
int main()
{
std::cout << "Enter an integer: ";
int x{};
std::cin >> x;
std::cout << "Enter another integer: ";
int y{};
std::cin >> y;
std::cout << std::boolalpha; // выводим логические значения как true или false
std::cout << x << " and " << y << " are equal? ";
std::cout << isEqual(x, y); // вернет true или false
return 0;
}
Ниже показан результат двух запусков этой программы:
Enter an integer: 5
Enter another integer: 5
5 and 5 are equal? true
Enter an integer: 6
Enter another integer: 4
6 and 4 are equal? false
Как это работает? Сначала мы читаем целочисленные значения для x и y. Затем вычисляется выражение isEqual(x, y). При первом запуске это приводит к вызову функции isEqual(5, 5). Внутри этой функции вычисляется 5 == 5, возвращая значение true. Значение true возвращается вызывающей функции для печати с помощью std::cout. При втором запуске вызов isEqual(6, 4) возвращает значение false.
К логическим значениям нужно немного привыкнуть, но как только вы начнете думать о них, они сразу же покажут свою простоту! Логические значения также являются огромной частью языка – вы в конечном итоге будете использовать их чаще, чем все другие базовые типы вместе взятые!
Мы продолжим изучение логических значений в следующем уроке.
