Hubbry Logo
search
logo
2099491

Boolean data type

logo
Community Hub0 Subscribers
Read side by side
from Wikipedia
George Boole

In computer science, the Boolean (sometimes shortened to Bool) is a data type that has one of two possible values (usually denoted true and false) which is intended to represent the two truth values of logic and Boolean algebra. It is named after George Boole, who first defined an algebraic system of logic in the mid 19th century. The Boolean data type is primarily associated with conditional statements, which allow different actions by changing control flow depending on whether a programmer-specified Boolean condition evaluates to true or false. It is a special case of a more general logical data type—logic does not always need to be Boolean (see probabilistic logic).

Generalities

[edit]

In programming languages with a built-in Boolean data type, such as Pascal, C, Python or Java, the comparison operators such as > and are usually defined to return a Boolean value. Conditional and iterative commands may be defined to test Boolean-valued expressions.

Languages with no explicit Boolean data type, like C90 and Lisp, may still represent truth values by some other data type. Common Lisp uses an empty list for false, and any other value for true. The C programming language uses an integer type, where relational expressions like i > j and logical expressions connected by && and || are defined to have value 1 if true and 0 if false, whereas the test parts of if, while, for, etc., treat any non-zero value as true.[1][2] Indeed, a Boolean variable may be regarded (and implemented) as a numerical variable with one binary digit (bit), or as a bit string of length one, which can store only two values. The implementation of Booleans in computers are most likely represented as a full word, rather than a bit; this is usually due to the ways computers transfer blocks of information.

Most programming languages, even those with no explicit Boolean type, have support for Boolean algebraic operations such as conjunction (AND, &, *), disjunction (OR, |, +), equivalence (EQV, =, ==), exclusive or/non-equivalence (XOR, NEQV, ^, !=, ¬), and negation (NOT, ~, !, ¬).

In some languages, like Ruby, Smalltalk, and Alice the true and false values belong to separate classes, e.g., True and False, respectively, so there is no one Boolean type.

In SQL, which uses a three-valued logic for explicit comparisons because of its special treatment of Nulls, the Boolean data type (introduced in SQL:1999) is also defined to include more than two truth values, so that SQL Booleans can store all logical values resulting from the evaluation of predicates in SQL. A column of Boolean type can be restricted to just TRUE and FALSE though.

Language-specific implementations

[edit]

ALGOL and the built-in BOOLEAN type

[edit]

One of the earliest programming languages to provide an explicit BOOLEAN data type is ALGOL 60 (1960) with values true and false and logical operators denoted by symbols '' (and), '' (or), '' (implies), '' (equivalence), and '' (not). Due to input device and character set limits on many computers of the time, however, most compilers used alternative representations for many of the operators, such as AND or 'AND'.

This approach with BOOLEAN as a built-in (either primitive or otherwise predefined) data type was adopted by many later programming languages, such as Simula 67 (1967), ALGOL 68 (1970),[3] Pascal (1970), Ada (1980), Java (1995), and C# (2000), among others.

C, C++, D, Objective-C, AWK

[edit]

Initial implementations of the language C (1972) provided no Boolean type, and to this day Boolean values are commonly represented by integers (ints) in C programs. The comparison operators (>, ==, etc.) are defined to return a signed integer (int) result, either 0 (for false) or 1 (for true). Logical operators (&&, ||, !, etc.) and condition-testing statements (if, while) assume that zero (and hence a NULL pointer or a null string terminator '\0' also) is false and all other values are true.

After enumerated types (enums) were added to the American National Standards Institute version of C, ANSI C (1989), many C programmers got used to defining their own Boolean types as such, for readability reasons. However, enumerated types are equivalent to integers according to the language standards; so the effective identity between Booleans and integers is still valid for C programs.

Standard C (since C99) provides a Boolean type, called _Bool. Since C23, the Boolean is now a core data type called bool, with values true and false (previously these were provided by macros from the header stdbool.h, which is now obsolete). The language guarantees that any two true values will compare equal (which was impossible to achieve before the introduction of the type). Boolean values still behave as integers, can be stored in integer variables, and used anywhere integers would be valid, including in indexing, arithmetic, parsing, and formatting. This approach (Boolean values are just integers) has been retained in all later versions of C. Note, that this does not mean that any integer value can be stored in a Boolean variable.

C++ has had the Boolean data type bool since C++98, but with automatic conversions from scalar and pointer values that are very similar to those of C. This approach was adopted also by many later languages, especially by some scripting languages such as AWK.

The D programming language has a proper Boolean data type bool. The bool type is a byte-sized type that can only hold the value true or false. The only operators that can accept operands of type bool are: &, |, ^, &=, |=, ^=, !, &&, || and ?:. A bool value can be implicitly converted to any integral type, with false becoming 0 and true becoming 1. The numeric literals 0 and 1 can be implicitly converted to the bool values false and true, respectively. Casting an expression to bool means testing for 0 or !=0 for arithmetic types, and null or !=null for pointers or references.

Objective-C also has a separate Boolean data type BOOL, with possible values being YES or NO, equivalents of true and false respectively.[4] Also, in Objective-C compilers that support C99, C's _Bool type can be used, since Objective-C is a superset of C.

Forth

[edit]

Forth (programming language) has no Boolean type, it uses regular integers: value 0 (all bits low) represents false, and -1 (all bits high) represents true. This allows the language to define only one set of logical operators, instead of one for mathematical calculations and one for conditions.[5]

Fortran

[edit]

The first version of FORTRAN (1957) and its successor FORTRAN II (1958) have no logical values or operations; even the conditional IF statement takes an arithmetic expression and branches to one of three locations according to its sign; see arithmetic IF. FORTRAN IV (1962), however, follows the ALGOL 60 example by providing a Boolean data type (LOGICAL), truth literals (.TRUE. and .FALSE.), logical IF statement, Boolean-valued numeric comparison operators (.EQ., .GT., etc.), and logical operators (.AND., .OR., and .NOT.). In FORMAT statements, a specific format descriptor ('L') is provided for the parsing or formatting of logical values. A common extension prior to FORTRAN 77 was to extend the .EQ. and .NE. operators, or perhaps add a .XOR. operator for comparing Boolean expressions.[6] Fortran 77 added .EQV. and .NEQV. operators to standardize the operations. Fortran 90 added alternative comparison operators <, <=, ==, /=, >, and >=.

Java

[edit]

In Java, the value of the boolean data type can only be either true or false.[7]

Lisp and Scheme

[edit]

The language Lisp (1958) never had a built-in Boolean data type. Instead, conditional constructs like cond assume that the logical value false is represented by the empty list (), which is defined to be the same as the special atom nil or NIL; whereas any other s-expression is interpreted as true. For convenience, most modern dialects of Lisp predefine the atom t to have value t, so that t can be used as a mnemonic notation for true.

This approach (any value can be used as a Boolean value) was retained in most Lisp dialects (Common Lisp, Scheme, Emacs Lisp), and similar models were adopted by many scripting languages, even ones having a distinct Boolean type or Boolean values; although which values are interpreted as false and which are true vary from language to language. In Scheme, for example, the false value is an atom distinct from the empty list, so the latter is interpreted as true. Common Lisp, on the other hand, also provides the dedicated boolean type, derived as a specialization of the symbol.[8]

Pascal, Ada, and Haskell

[edit]

The language Pascal (1970) popularized the concept of programmer-defined enumerated types, previously available with different nomenclature in COBOL, FACT and JOVIAL. A built-in Boolean data type was then provided as a predefined enumerated type with values FALSE and TRUE. By definition, all comparisons, logical operations, and conditional statements applied to and/or yielded Boolean values. Otherwise, the Boolean type had all the facilities which were available for enumerated types in general, such as ordering and use as indices. In contrast, converting between Booleans and integers (or any other types) still required explicit tests or function calls, as in ALGOL 60. This approach (Boolean is an enumerated type) was adopted by most later languages which had enumerated types, such as Modula, Ada, and Haskell.

Perl and Lua

[edit]

Perl has no Boolean data type. Instead, any value can behave as Boolean in Boolean context (condition of if or while statement, argument of && or ||, etc.). The number 0, the strings "0" and "", the empty list (), and the special value undef evaluate to false.[9] All else evaluates to true.

Lua has a Boolean data type, but non-Boolean values can also behave as Booleans. The non-value nil evaluates to false, whereas every other data type value evaluates to true. This includes the empty string "" and the number 0, which are very often considered false in other languages.

PL/I

[edit]

PL/I has no Boolean data type. Instead, comparison operators generate BIT(1) values; '0'B represents false and '1'B represents true. The operands of, e.g., &, |, ¬, are converted to bit strings and the operations are performed on each bit. The element-expression of an IF statement is true if any bit is 1.

Python and Ruby

[edit]

Python, from version 2.3 forward, has a bool type which is a subclass of int, the standard integer type.[10] It has two possible values: True and False, which are special versions of 1 and 0 respectively and behave as such in arithmetic contexts. Also, a numeric value of zero (integer or fractional), the null value (None), the empty string, and empty containers (lists, sets, etc.) are considered Boolean false; all other values are considered Boolean true by default.[11] Classes can define how their instances are treated in a Boolean context through the special method __nonzero__ (Python 2) or __bool__ (Python 3). For containers, __len__ (the special method for determining the length of containers) is used if the explicit Boolean conversion method is not defined.

In Ruby, in contrast, only nil (Ruby's null value) and a special false object are false; all else (including the integer 0 and empty arrays) is true.

Rexx

[edit]

Rexx has no Boolean data type. Instead, comparison operators generate 0 or 1; 0 represents false and 1 represents true. The operands of, e.g., &, |, ¬, must be 0 or 1.

SQL

[edit]

Booleans appear in SQL when a condition is needed, such as WHERE clause, in form of predicate which is produced by using operators such as comparison operators, IN operator, IS (NOT) NULL etc. However, apart from TRUE and FALSE, these operators can also yield a third state, called UNKNOWN, when comparison with NULL is made.

The SQL92 standard introduced IS (NOT) TRUE, IS (NOT) FALSE, and IS (NOT) UNKNOWN operators which evaluate a predicate, which predated the introduction of Boolean type in SQL:1999.

The SQL:1999 standard introduced a BOOLEAN data type as an optional feature (T031). When restricted by a NOT NULL constraint, a SQL BOOLEAN behaves like Booleans in other languages, which can store only TRUE and FALSE values. However, if it is nullable, which is the default like all other SQL data types, it can have the special null value also. Although the SQL standard defines three literals for the BOOLEAN type – TRUE, FALSE, and UNKNOWN — it also says that the NULL BOOLEAN and UNKNOWN "may be used interchangeably to mean exactly the same thing".[12][13] This has caused some controversy because the identification subjects UNKNOWN to the equality comparison rules for NULL. More precisely UNKNOWN = UNKNOWN is not TRUE but UNKNOWN/NULL.[14] As of 2012 few major SQL systems implement the T031 feature.[15] Firebird and PostgreSQL are notable exceptions, although PostgreSQL implements no UNKNOWN literal; NULL can be used instead.[16]

The treatment of Boolean values differs between SQL systems.

For example, in Microsoft SQL Server, Boolean value is not supported at all, neither as a standalone data type nor representable as an integer. It shows the error message "An expression of non-Boolean type specified in a context where a condition is expected" if a column is directly used in the WHERE clause, e.g. SELECT a FROM t WHERE a, while a statement such as SELECT column IS NOT NULL FROM t yields a syntax error. The BIT data type, which can only store integers 0 and 1 apart from NULL, is commonly used as a workaround to store Boolean values, but workarounds need to be used such as UPDATE t SET flag = IIF(col IS NOT NULL, 1, 0) WHERE flag = 0 to convert between the integer and Boolean expression.

Microsoft Access, which uses the Access Database Engine (ACE/JET),[17] also does not have a Boolean data type. Similar to MS SQL Server, it uses a BIT data type.[18] In Access it is known as a Yes/No data type[19] which can have two values; Yes (True) or No (False). The BIT data type in Access can also be represented numerically: True is −1 and False is 0.[20] This differs from MS SQL Server in two ways, even though both are Microsoft products:

  1. Access represents TRUE as −1, while it is 1 in SQL Server
  2. Access does not support the Null tri-state, supported by SQL Server

PostgreSQL has a distinct BOOLEAN type as in the standard,[21] which allows predicates to be stored directly into a BOOLEAN column, and allows using a BOOLEAN column directly as a predicate in a WHERE clause.

In MySQL, BOOLEAN is treated as an alias of TINYINT(1);[22] TRUE is the same as integer 1 and FALSE is the same as integer 0.[23] Any non-zero integer is true in conditions.

Tableau

[edit]

Tableau Software has a BOOLEAN data type.[24] The literal of a Boolean value is True or False.[25]

The Tableau INT() function converts a Boolean to a number, returning 1 for True and 0 for False.[26]

Tcl

[edit]

Tcl has no separate Boolean type. Like in C, the integers 0 (false) and 1 (true—in fact any nonzero integer) are used.[27]

Examples of coding:

 set v 1
 if { $v } { puts "V is 1 or true" }

The above will show V is 1 or true since the expression evaluates to 1.

 set v ""
 if { $v } ....

The above will render an error, as variable v cannot be evaluated as 0 or 1.

Truthy

[edit]

In some programming languages, any expression can be evaluated in a context that expects a Boolean data type. Typically (though this varies by programming language) expressions like the number zero, the empty string, empty lists, and null are treated as false, and strings with content (like "abc"), other numbers, and objects evaluate to true. Sometimes these classes of expressions are called falsy and truthy. For example, in Lisp, nil, the empty list, is treated as false, and all other values are treated as true. In C, the number 0 or 0.0 is false, and all other values are treated as true.

In JavaScript, the empty string (""), null, undefined, NaN, +0, −0 and false[28] are sometimes called falsy (of which the complement is truthy) to distinguish between strictly type-checked and coerced Booleans (see also: JavaScript syntax#Type conversion).[29] As opposed to Python, empty containers (Arrays, Maps, Sets) are considered truthy. Languages such as PHP also use this approach.

See also

[edit]

References

[edit]
Revisions and contributorsEdit on WikipediaRead on Wikipedia
from Grokipedia
The Boolean data type, often abbreviated as bool, is a fundamental primitive data type in computer science and programming languages that represents one of two mutually exclusive truth values: true or false.[1][2] These values correspond directly to the logical outcomes in Boolean algebra, enabling the expression and evaluation of conditions, decisions, and binary states within computational logic.[3] Typically implemented using a single bit of storage (0 for false and 1 for true), the Boolean type underpins control flow structures like if-statements and loops, as well as relational and logical operations such as equality checks, conjunction (AND), disjunction (OR), and negation (NOT).[4][5] Named after the English mathematician and logician George Boole (1815–1864), the Boolean data type draws from his pioneering work in developing Boolean algebra, first outlined in his 1847 book The Mathematical Analysis of Logic and expanded in An Investigation of the Laws of Thought (1854), which formalized operations on binary variables to model deductive reasoning.[6] Boole's algebraic system, operating on variables that could only assume "true" or "false" states, laid the theoretical foundation for digital circuit design and modern computing, influencing early computer architects like Claude Shannon, who in 1937 demonstrated its application to electrical switching circuits.[7] Although Boolean logic predates electronic computers, its explicit adoption as a data type in programming emerged in the late 1950s and early 1960s, marking a shift from implicit representations (e.g., using integers as proxies for truth values in early languages like Fortran I) to dedicated types for clarity and type safety.[8] The Boolean type first appeared as a standard feature in ALGOL 60 (1960), one of the earliest high-level languages to include it alongside integer and real types, allowing variables to be declared as boolean with literal values true and false for use in conditional expressions and logical operators.[9][10] Subsequent languages like Fortran IV (1962) introduced a LOGICAL type with .TRUE. and .FALSE. literals, while modern languages such as C (via the <stdbool.h> header since 1999), Java, Python, and SQL standardize it for portability and expressiveness.[8] In practice, Booleans facilitate everything from simple flag variables indicating states (e.g., is_valid) to complex algorithms in databases, artificial intelligence, and software verification, where they enable precise modeling of propositions and predicates.[11] Despite its simplicity, the type's binary nature aligns with the underlying binary representation of all digital data, making it indispensable for efficient computation and error-free logical reasoning in software systems.[12]

History and Origins

Boolean Algebra Foundations

The Boolean data type originates from the mathematical framework developed by George Boole in the mid-19th century, which formalized logic using algebraic symbols restricted to binary truth values of true and false. In 1847, Boole published The Mathematical Analysis of Logic, a pamphlet that introduced a calculus for deductive reasoning by treating logical propositions as variables that could only assume one of two values, laying the groundwork for symbolic manipulation of truth.[13] This work was expanded in his 1854 book An Investigation of the Laws of Thought, where he systematically explored the laws governing these binary symbols, establishing Boolean algebra as a distinct branch of mathematics that models human reasoning through precise, equation-like operations.[14] At the core of Boolean algebra are fundamental principles that define how these binary variables interact, including idempotence, which states that a variable combined with itself yields the same value—formally, $ A \land A = A $ and $ A \lor A = A $—ensuring operations are self-consistent without accumulation.[15] Complementarity asserts that each variable has an inverse such that $ A \land \neg A = \bot $ (false) and $ A \lor \neg A = \top $ (true), where $ \neg $ denotes negation and $ \bot, \top $ represent the constant false and true, respectively.[15] The distributive laws further enable restructuring of expressions, such as conjunction distributing over disjunction:
A(BC)=(AB)(AC) A \land (B \lor C) = (A \land B) \lor (A \land C)

and disjunction over conjunction:
A(BC)=(AB)(AC), A \lor (B \land C) = (A \lor B) \land (A \lor C),

allowing complex logical statements to be simplified or expanded algebraically.[15]
These algebraic foundations transitioned to practical applications in electrical engineering through Claude Shannon's 1937 master's thesis, A Symbolic Analysis of Relay and Switching Circuits, which demonstrated that Boolean operations could directly model the behavior of electrical switches and relays in binary circuits.[16] Shannon showed that relay contacts—either closed (true) or open (false)—correspond to Boolean variables, with series connections representing conjunction (AND) and parallel connections representing disjunction (OR), thus bridging symbolic logic to physical hardware design.[16] The primary binary operations in Boolean algebra are conjunction (AND, denoted $ \land $), disjunction (OR, denoted $ \lor $), and negation (NOT, denoted $ \neg $), each defined by exhaustive truth tables that enumerate all input combinations and outputs.[15] The truth table for AND is as follows:
ABA ∧ B
TTT
TFF
FTF
FFF
For OR:
ABA ∨ B
TTT
TFT
FTT
FFF
And for NOT (unary):
A¬A
TF
FT
These tables, implicit in Boole's algebraic derivations and explicitly analyzed by Shannon for circuit synthesis, provide a complete specification of the operations' behavior.[16]

Adoption in Early Computing

The adoption of Boolean data types in early computing bridged abstract Boolean algebra to practical implementations in hardware and programming languages, enabling efficient representation of logical conditions through binary states. In 1945, John von Neumann's "First Draft of a Report on the EDVAC" described the logical structure of computing elements using discrete states, implicitly relying on binary elements that could represent two distinct conditions, such as on/off or true/false, to form the basis of digital logic control.[17] This conceptual foundation influenced subsequent hardware designs, where binary states facilitated conditional operations. For instance, the IBM 701, introduced in 1952 as IBM's first commercial scientific computer, incorporated bit-level flags for handling conditions like overflow and sign, allowing instructions such as "Transfer on Overflow" to branch based on these binary indicators.[18] The 1940s and 1950s saw cybernetics and automata theory further promote Boolean primitives in low-level programming, emphasizing feedback and state machines that aligned with binary decision-making. These fields, pioneered by figures like Norbert Wiener, inspired the integration of Boolean-like flags in early assemblers for machines such as the UNIVAC I (delivered in 1951), where binary bits served as condition codes in symbolic assembly languages to manage control flow and error states.[19] Such hardware-level adoption made Boolean representation a natural primitive for expressing logical decisions in machine code, paving the way for higher-level languages. Programming languages began explicitly incorporating Boolean types in the late 1950s, formalizing these hardware concepts for algorithmic expression. Lisp, developed by John McCarthy starting in 1958, treated booleans as symbols where T represented true and NIL (the empty list) represented false, enabling symbolic manipulation of truth values in list-processing contexts.[20] This approach marked an early milestone in software, influencing AI and symbolic computing. Similarly, Fortran IV (1962) introduced the LOGICAL type with literals .TRUE. and .FALSE., supporting conditional statements and arithmetic comparisons for scientific computations.[21] ALGOL 60 (1960) further standardized BOOLEAN as a built-in scalar type for conditional expressions, defining it alongside integer and real types to denote logical properties of values in block-structured programs.[22] These implementations solidified Boolean types as essential for control flow, distinct from numerical data.

Core Concepts

Definition and Standard Values

The Boolean data type is a fundamental scalar data type in computer science, characterized by exactly two distinct values that represent the truth values of logic: true and false.[23] These values correspond to logical truth and falsehood, often mapped internally to non-zero (typically 1) for true and zero for false, enabling binary decision-making in computational processes.[24] This binary structure underpins the type's role in formalizing logical propositions without ambiguity.[25] Standard literals for the Boolean type vary slightly across languages but follow consistent conventions for readability. In most modern programming languages, such as C++, Java, and Python, the literals are written in lowercase as true and false.[26][27] In contrast, languages like Fortran and SQL use uppercase forms: .TRUE. and .FALSE. in Fortran, and TRUE and FALSE in SQL standards.[28][29] Booleans are typically implemented as primitive, immutable types that cannot hold null values or subtypes, ensuring they remain atomic and reliable for logical operations.[27][30] This design prevents unintended states, reinforcing their use as simple flags without derivable variants.[31] In programming, the Boolean data type plays a central role in control flow, serving as the condition in if and while statements, comparison expressions, and assertions to direct program execution based on logical outcomes.[23] Unlike fuzzy logic systems, which permit intermediate truth degrees between 0 and 1 for nuanced reasoning, Booleans enforce a strict binary distinction with no such intermediates, prioritizing crisp, deterministic logic in standard computing.[32]

Boolean Logic Principles

Boolean logic principles form the foundational rules that govern operations on Boolean values, ensuring consistent and predictable behavior in logical expressions. Central to these principles are the laws of thought, as formalized in algebraic terms by George Boole. The law of identity states that a proposition is equivalent to itself, expressed as $ A = A $. The law of non-contradiction asserts that a proposition cannot be both true and false simultaneously, given by $ \neg (A \land \neg A) $. The law of excluded middle declares that every proposition is either true or false, represented as $ A \lor \neg A $. These laws provide the axiomatic basis for Boolean reasoning, prohibiting inconsistencies and ensuring exhaustive coverage of possibilities.[15] Complementing these are De Morgan's laws, which facilitate the transformation of logical expressions involving negation. The first law equates the negation of a conjunction to the disjunction of the negations: $ \neg (A \land B) = \neg A \lor \neg B $. The second law states that the negation of a disjunction is the conjunction of the negations: $ \neg (A \lor B) = \neg A \land \neg B $. These equivalences, introduced by Augustus De Morgan, are essential for simplifying complex negations and proving the duality between conjunction and disjunction in Boolean algebra.[33] At a structural level, the set of Boolean values under specific operations constitutes a field, specifically the finite field GF(2). Here, addition is defined as exclusive or (XOR), and multiplication as logical AND, with the properties of commutativity, associativity, distributivity, and the existence of identities and inverses holding true. This field structure, explored in the context of Boolean rings, underscores the algebraic closure of Boolean logic and its isomorphism to modular arithmetic modulo 2. Boolean expressions can be classified as tautologies, which are always true regardless of the values of their variables, or contradictions, which are always false. For instance, $ A \lor \neg A $ exemplifies a tautology, directly embodying the law of excluded middle. Conversely, $ A \land \neg A $ is a contradiction, aligning with the law of non-contradiction. Simplification rules further aid in reducing expressions; idempotence dictates that $ A \land A = A $ and $ A \lor A = A $, while absorption laws yield $ A \land (A \lor B) = A $ and $ A \lor (A \land B) = A $. These rules, derivable from the core axioms, enable efficient manipulation and verification of logical statements.[15]

Operations and Expressions

Logical Operators and Precedence

The unary NOT operator, denoted as ¬\neg or !, inverts the truth value of a single Boolean operand, yielding true if the operand is false and false if the operand is true. For instance, ¬\neg true equals false. This operator is fundamental in Boolean algebra, allowing the negation of propositions.[34] The binary AND operator, denoted as \land or &&, evaluates to true only when both operands are true; otherwise, it returns false. Its behavior is captured in the following truth table:
ABA \land B
truetruetrue
truefalsefalse
falsetruefalse
falsefalsefalse
This operator corresponds to logical conjunction, where the result holds if all conditions are satisfied.[35] The binary OR operator, denoted as \lor or ||, evaluates to true if at least one operand is true and false only if both are false; this is known as inclusive OR. Its truth table is:
ABA \lor B
truetruetrue
truefalsetrue
falsetruetrue
falsefalsefalse
In contrast, the exclusive OR (XOR), denoted as \oplus or ^, returns true if the operands differ in truth value (exactly one is true) and false otherwise. The XOR truth table is:
ABA \oplus B
truetruefalse
truefalsetrue
falsetruetrue
falsefalsefalse
XOR is useful for detecting differences or toggling states and can be expressed using other operators as (A \land ¬\negB) \lor (B \land ¬\negA). Logical operators follow a standard precedence hierarchy to resolve the order of operations in expressions without explicit parentheses: NOT has the highest precedence, followed by AND, then OR, with XOR typically positioned between AND and OR. For example, the expression A \land B \lor C is interpreted as (A \land B) \lor C, while ¬\negA \land B equals (¬\negA) \land B. This convention minimizes ambiguity in compound expressions.[36][37] AND and OR are left-associative, meaning they group from left to right in chains of the same operator: A \land B \land C parses as (A \land B) \land C, and similarly for OR. This associativity ensures consistent evaluation, as in the expression true \lor false \land true, which becomes true \lor (false \land true) and evaluates to true. NOT, being unary, applies directly to its operand without associativity concerns in multi-operator contexts.[38]

Short-Circuit and Side-Effect Evaluation

Short-circuit evaluation is a runtime optimization in Boolean expressions where the evaluation of operands stops as soon as the overall result can be determined. For the logical AND operator, if the left operand evaluates to false, the right operand is not evaluated, as the entire expression is false. Similarly, for the logical OR operator, if the left operand is true, the right operand is skipped, as the expression is true. This behavior is standard for the && and || operators in C++, where the language specification mandates short-circuiting to ensure predictable control flow. The primary benefit of short-circuit evaluation is improved efficiency, as it avoids executing potentially costly computations or function calls in the unevaluated operands, particularly useful when the second operand involves complex operations or side-effecting procedures. This optimization has been a common feature in many programming languages since the 1970s, enhancing performance without altering the logical semantics of expressions.[39] Short-circuit evaluation can be implemented in ALGOL 68 using user-defined operators such as ANDIF and ORELSE (or standard examples like andf and orf), designed to allow conditional evaluation of operands and prevent errors from unconditional calls to procedures with side effects in Boolean expressions.[40] However, short-circuit evaluation can lead to unintended side effects when expressions include operations that modify state, such as assignments or increments. For instance, in C, the expression if (x != 0 && (y = 42 / x)) will skip the division and assignment to y if x is zero, potentially leaving y unchanged when the programmer expects it to be set, which may cause bugs in programs relying on those modifications. In some languages like Python, short-circuit behavior is provided by the keywords and and or, which evaluate lazily and return the last evaluated operand rather than a strict Boolean, but this is optional and distinct from bitwise operators; programmers must be cautious with side effects in these expressions to avoid skipped executions.[41]

Internal Representations

Memory and Bit-Level Storage

In computer memory, the Boolean data type is conceptually represented using a single bit to encode its two states: 0 for false and any non-zero value (typically 1) for true. However, due to hardware constraints and the minimum addressable unit of memory being one byte, individual Boolean variables are commonly allocated one full byte (8 bits) in implementations of languages like C and C++, where sizeof(_Bool) or sizeof(bool) returns 1. This allocation facilitates direct memory addressing and avoids the overhead of bit-level operations for isolated variables. Memory alignment further influences storage, as compilers pad Boolean members in structures to align with the system's natural boundaries (often 1, 4, or 8 bytes) for efficient access. For instance, a bool in C++ typically has an alignment of 1 byte, but adjacent fields may introduce padding bytes to satisfy stricter alignment rules for larger types like int. Endianness, which determines byte order in multi-byte integers, has no impact on single-bit or single-byte Boolean storage, as it operates at the byte level.[42] To achieve denser storage for multiple Booleans, bit packing techniques use bitmasks or bit-fields to combine several into a single integer or storage unit. In C, the C99 standard's _Bool type supports this via bit-fields in structs, such as struct { _Bool a:1; _Bool b:1; _Bool c:1; };, which packs three Booleans into one byte using bitwise operations for access (e.g., flags = 0b101 for true, false, true). The C99 _Bool is defined as an integer type holding 0 or 1, with a size of at least 1 byte in practice across implementations.[43] The C23 standard introduces the bool keyword as a core type, with true and false as predefined constants, while deprecating reliance on the macros provided by <stdbool.h> for compatibility. The type holds values 0 (false) or 1 (true), with sizeof(bool) being at least 1 byte in practice across implementations. Compilers optimize Boolean handling by eliminating unused variables through dead code elimination and potentially storing active ones in CPU registers rather than memory during evaluation.[44][45]

Hardware and Digital Logic Integration

The Boolean data type finds its foundational implementation in digital hardware through logic gates constructed from transistors, which directly realize Boolean operations at the circuit level. Basic gates such as AND, OR, and NOT are built using complementary metal-oxide-semiconductor (CMOS) technology, where n-type (NMOS) and p-type (PMOS) transistors form pull-down and pull-up networks to control output states based on input combinations. For instance, a CMOS NAND gate, which serves as a universal gate capable of implementing any Boolean function when combined appropriately, consists of two PMOS transistors in parallel for the pull-up network and two NMOS transistors in series for the pull-down network, enabling efficient inversion of the AND operation.[46][47] In CMOS logic, Boolean values are represented by distinct voltage levels: a logic high (1 or true) corresponds to a voltage near the supply rail (typically 3.3V or 5V), while a logic low (0 or false) is near ground (0V), with thresholds defined such that inputs above approximately 70% of the supply voltage are interpreted as high and below 30% as low to ensure reliable switching and noise immunity.[48] This binary voltage encoding allows transistors to act as switches, where a high input turns off PMOS transistors (preventing current to Vdd) and turns on NMOS transistors (allowing current to ground), or vice versa, thereby computing the Boolean output without intermediate states.[49] Within central processing units (CPUs), Boolean-like behavior is integrated via status registers that include flags representing computational outcomes, such as the zero flag (ZF), which is set to 1 (true) if the result of an arithmetic or logical operation equals zero and cleared to 0 (false) otherwise, enabling conditional branching based on equality checks.[50] These single-bit flags operate as hardware Booleans, directly influencing control flow in instruction execution pipelines. In field-programmable gate arrays (FPGAs) and application-specific integrated circuits (ASICs), Boolean values map seamlessly to physical hardware elements: combinational logic corresponds to interconnect wires carrying high or low signals, while sequential storage uses flip-flops to hold Boolean states across clock cycles, allowing designers to synthesize Boolean expressions into reconfigurable or custom circuits with minimal abstraction.[51] The use of single-bit Boolean operations in hardware contributes to power efficiency, particularly in embedded systems, where minimizing transistor switching reduces dynamic energy consumption—often by orders of magnitude compared to multi-bit arithmetic—enabling battery-powered devices to perform conditional logic with sub-microwatt overhead per gate.[52][53]

Language Implementations

Early Procedural Languages

In ALGOL 68, the Boolean type is declared as the mode BOOL, which encompasses exactly two values: true and false.[54] This mode is a primitive type with strong static typing, ensuring that Boolean values cannot be implicitly converted to or from other modes without explicit coercion, promoting type safety in expressions and conditionals.[55] Boolean expressions are central to control structures, such as the if statement, where a BOOL value determines the selection of alternative actions, reflecting the language's emphasis on formal semantics and orthogonality in its 1968-1973 design.[56] Fortran implementations up to the 1977 ANSI standard introduced the LOGICAL data type, limited to the values .TRUE. and .FALSE., with storage typically occupying one processor word but allowing non-standard extensions like LOGICAL*1 through LOGICAL*8 for varying byte lengths in vendor-specific compilers.[57] Arithmetic operations on LOGICAL variables are explicitly forbidden to prevent misuse, aligning with Fortran's focus on numerical computation where logicals serve primarily for conditional branching in IF statements and relational comparisons.[58] This design, rooted in earlier Fortran versions from the 1950s, prioritized efficiency in scientific simulations over general-purpose expressiveness.[57] PL/I, developed by IBM in the mid-1960s as a versatile language for both scientific and business applications, represents Booleans using the BIT(1) data type, where a value of '1'B denotes true and '0'B denotes false.[59] This bit-string approach integrates seamlessly with conditionals, allowing BIT(1) expressions to control IF and DO statements directly, and supports Boolean operations like AND, OR, and NOT on bit aggregates for efficient packed storage.[59] As IBM's proposed standard for System/360 computers, PL/I's Boolean handling emphasized compatibility with low-level bit manipulation while providing high-level control flow.[60] Pascal, standardized in ISO 7185 (extended from Wirth's 1970 design), defines boolean as a predefined ordinal type with the ordered values false (0) and true (1), declared implicitly in every program and case-insensitive in usage.[61] Unlike numeric types, boolean supports no arithmetic but is integral to relational operators and control structures like if-then-else, enforcing strict typing to avoid implicit conversions and support structured programming paradigms.[61] The type's lowercase naming and enumeration basis highlight Pascal's pedagogical focus on clarity and simplicity. ALGOL 68's orthogonal and strongly typed BOOL influenced subsequent structured languages like Pascal by promoting explicit mode declarations and expression-based conditionals, contrasting with Fortran's more rigid, numerically oriented LOGICAL that restricted operations to maintain computational reliability in scientific contexts.[62] PL/I's BIT(1) offered a flexible, bit-level integration suited to IBM's enterprise environments, bridging high-level control and low-level efficiency in ways less emphasized in ALGOL 68 or Pascal.[60] Overall, these implementations from the 1960s-1970s balanced expressiveness with hardware constraints, with ALGOL 68 prioritizing formalism and Fortran utility in procedural workflows.[63]

Systems and Low-Level Languages

In pre-C99 versions of the C programming language, there was no built-in boolean data type; instead, programmers conventionally used the integer type int to represent boolean values, where 0 denoted false and any non-zero value denoted true.[64] This approach allowed flexibility in low-level operations but relied on implicit conventions for logical expressions and control flow. For example, standard library functions like the isspace() macro from <ctype.h> returned an int value of 0 for false or non-zero for true, enabling direct use in conditional statements without explicit casting.[65] The C++ programming language introduced a dedicated bool type in the 1998 ISO standard (C++98), which explicitly holds only the values true (internally represented as 1) or false (0), promoting type safety in systems programming. This type occupies typically 1 byte of storage and supports implicit conversions from integers (non-zero to true, 0 to false), though modern compilers often issue warnings for such conversions to prevent unintended side effects in low-level code. Logical operators like &&, ||, and ! operate directly on bool operands, integrating seamlessly with hardware-level bit manipulations while enforcing stricter semantics than C's integer-based approach. In the Forth programming language, boolean values are handled as flags on the data stack, with true represented as -1 (all bits set) and false as 0, allowing efficient bitwise and conditional operations in resource-constrained environments.[66] Stack-based logical operations, such as AND? (which performs a bitwise AND and tests for non-zero) and OR? (bitwise OR with non-zero test), enable compact, low-level control flow without dedicated types, emphasizing manual stack management for embedded systems.[66] This representation facilitates direct hardware interaction, as -1 inverts to 0 via bitwise NOT, aligning with Forth's postfix notation and minimal runtime overhead. AWK, a text-processing language often used in systems scripting, treats boolean contexts implicitly: any non-zero numeric value or non-empty string evaluates to true, while 0 or the empty string ("") evaluates to false, without a distinct boolean type. For explicit boolean handling, values are typically set to 1 (true) or 0 (false), integrating with pattern-action rules where conditions like if ($1 != 0) leverage this implicit conversion for low-level data parsing tasks. The D programming language defines bool as a 1-byte type that strictly holds only true or false, mirroring C++'s design but with enforced type checking to avoid implicit integer promotions in low-level systems code.[67] Similarly, Objective-C uses BOOL, a typedef to signed char (1 byte), with constants YES (1) and NO (0), providing strict boolean semantics in a C-like foundation while warning against non-boolean assignments in compiled environments.

Object-Oriented and Statically Typed Languages

In object-oriented languages with static typing, the Boolean data type is typically implemented as a primitive type to ensure efficient representation and type safety, while object-oriented features provide wrapper classes or structures for integration with collections, generics, and inheritance hierarchies. These languages enforce strict typing rules, preventing implicit conversions from non-Boolean types to avoid errors in conditional logic and method dispatching. Logical operators such as AND, OR, and NOT are predefined for Boolean operands, supporting expressions in control structures like if-statements and loops. Java features a primitive boolean type with literal values true and false, defined in the Java Language Specification as having exactly two values without numeric representation.[68] The Boolean wrapper class, introduced in JDK 1.0, encapsulates a boolean value in an object, enabling its use in scenarios requiring reference types, such as collections or generics.[69] Autoboxing, added in Java 1.5, automatically converts between boolean primitives and Boolean objects during assignments and method calls, streamlining code while maintaining backward compatibility.[70] Ada defines Boolean in the standard Standard package as an enumeration type with literals False and True, providing a foundational type for logical expressions without implicit numeric conversions.[71] This enumerated nature integrates seamlessly with Ada's strong typing system, where Boolean expressions are used in preconditions and postconditions for subprograms to enforce contracts at compile-time or runtime.[72] The type supports predefined logical operators like and, or, and not, ensuring type-safe usage in object-oriented extensions such as tagged types and inheritance. C#, introduced in 2000 as part of the .NET Framework, uses the bool keyword as an alias for the System.Boolean structure, representing only true or false values with no underlying numeric encoding.[73] Static typing prohibits implicit conversions from integers or other types to bool, requiring explicit casts to prevent subtle bugs in conditional statements.[74] The nullable bool? variant, introduced in C# 2.0, allows representation of an undefined state alongside true and false, facilitating optional parameters in object-oriented designs like properties and methods.[75] Swift implements Bool as a value type (struct) in its standard library, supporting literals true and false for Boolean logic without enumeration semantics to optimize performance in generic programming.[76] It conforms to the Equatable protocol, enabling direct comparisons in collections and algorithms, and integrates with optionals as Bool? to handle nil cases in safe, statically checked code. This design emphasizes type safety, where non-Boolean expressions cannot implicitly coerce to Bool in control flow constructs. Rust provides a primitive bool type, occupying one byte in memory, with values true (represented as 1 when cast to integer) and false (0).[77] The language's static typing strictly forbids implicit conversions from other types, such as integers, to bool, ensuring explicit intent in conditions and pattern matching to enhance memory safety and prevent runtime errors. This approach aligns with Rust's ownership model, where bool values are used in object-oriented traits and generics without risking undefined behavior.

Scripting and Dynamically Typed Languages

In scripting and dynamically typed languages, the Boolean data type often integrates loosely with other types through implicit coercion mechanisms, where values are evaluated as "truthy" or "falsy" in conditional contexts rather than strictly requiring Boolean literals. This approach facilitates concise code but can introduce subtle behaviors depending on how non-Boolean values are interpreted. For instance, empty collections or zero-like values may coerce to falsy, enabling idiomatic expressions like checking for non-empty iterables without explicit comparisons.[41] In Python, the bool type is a subclass of int, with True equivalent to 1 and False to 0, allowing Boolean values to participate in arithmetic operations seamlessly.[78] In conditional statements, Python employs truth value testing: an object is truthy unless its __bool__() method returns False or its __len__() method returns zero, making empty sequences, iterables, or mappings falsy while non-empty ones are truthy.[41] For example:
if []:  # Falsy: empty list
    print("Non-empty")
else:
    print("Empty")  # This executes
This coercion promotes readable code for common checks, such as verifying iterable contents.[41] In alignment with PEP 8's style guidelines, Python programmers should prefer if x: or if not x: over if x == True: or if x == False:, as the former leverages truth value testing idiomatically and is more readable and flexible for handling various falsy values. Ruby treats true and false as singleton instances of TrueClass and FalseClass, respectively, which are immediate values optimized for performance.[79][80] In Boolean contexts, only false and nil are falsy; all other values, including non-empty strings, non-zero numbers, and objects, evaluate to truthy.[81] This design aligns with Ruby's emphasis on expressiveness, where methods ending in a question mark conventionally return truthy values for affirmative cases. For example:
if ""  # Truthy: non-nil, non-false
  puts "Truthy"
end
Such coercion avoids verbose nil checks, enhancing scripting fluency.[82] Perl lacks a dedicated Boolean type, instead using numeric 1 for true and 0 for false in most contexts, though it supports explicit true and false constants in modern versions via the builtin pragma.[83] In Boolean evaluation, values are falsy if they are the number 0, the strings '0' or '', undef, or an empty list (); all others, including non-zero numbers or non-special strings, are truthy.[84] Notably, strings like '00' are truthy because they do not match the exact falsy patterns. For example:
if ('0') { print "Falsy\n"; }  # Does not execute (falsy)
if ('00') { print "Truthy\n"; }  # Executes (truthy)
if (undef) { print "Falsy\n"; }  # Does not execute (falsy)
This scalar context interpretation, rooted in Perl's flexible typing, supports rapid prototyping but requires awareness of string-numeric ambiguities.[84] Lua provides a primitive boolean type with literal values true and false, which are distinct from other types.[85] In conditional statements, only nil and false are falsy; every other value—including 0, the empty string '', non-empty strings, and non-nil objects—is truthy, reflecting Lua's minimalistic coercion rules.[85] This uniformity simplifies control flow in embedded scripting scenarios. For example:
if 0 then  -- Truthy
    print("Truthy")
end
if '' then  -- Truthy
    print("Truthy")
end
Lua's approach avoids overloading zero or empty values as falsy, differing from languages like Python and promoting consistent non-Boolean usage in conditions.[85] JavaScript, introduced in 1995, features both a primitive boolean type (lowercase true/false) and a Boolean object wrapper, with the primitive preferred for efficiency.[86] Coercion to Boolean occurs via the abstract ToBoolean operation in contexts like if statements, where falsy values include false, 0, -0, 0n (BigInt zero), "", null, undefined, and NaN; all others are truthy.[87] The double negation !! operator explicitly converts to a primitive Boolean, as in !!0 yielding false. For example:
if (!![]) {  // Truthy: non-empty array
    console.log("Truthy");
}
This system enables dynamic web scripting but can lead to unexpected results without careful handling of edge cases like empty objects being truthy.[87]

Functional and Declarative Languages

In functional and declarative languages, the Boolean data type often integrates seamlessly with higher-order functions, pattern matching, and logical inference, emphasizing immutability and declarative specifications over imperative control flow. These languages typically treat booleans as first-class citizens that support lazy evaluation and predicate-based computations, where truth values influence function guards or query resolutions without explicit mutation.[88] Haskell defines the Bool type as an algebraic data type with two nullary constructors: data Bool = False | True, enabling pattern matching in function definitions.[88] Guards, introduced via the | symbol in function declarations, allow conditional branching based on boolean expressions, such as factorial 0 = 1; factorial n | n > 1 = n * factorial (n - 1); factorial _ = error "Negative input", where the first matching guard determines the computation path.[88] Lazy evaluation defers boolean computations until needed, optimizing expressions like infinite lists filtered by boolean predicates without immediate resolution.[88] In Lisp dialects, booleans are represented symbolically to align with list-processing paradigms. Common Lisp uses the type boolean, a subtype of symbol containing only t (true) and nil (false), where predicates like (evenp x) return these values for logical tests. Scheme, per the R5RS standard, employs #t for true and #f for false as the canonical boolean objects, with conditional forms like if treating any non-#f value as true; predicates such as (even? x) explicitly return booleans to facilitate functional composition.[89] REXX, particularly in its object-oriented variant (ooREXX), provides .true and .false as built-in constants representing boolean values, which can be used in conditional statements and logical operations.[90] However, boolean evaluations often coerce numeric or string inputs, treating 1 or truthy strings as .true and 0 or falsy strings as .false, enabling flexible declarative conditions in scripts.[90] Tcl handles booleans primarily through the expr command, which evaluates expressions to 1 (true) or 0 (false), supporting string-based truthiness where values like "yes", "true", or non-zero numbers convert to true.[91] The string is boolean subcommand verifies if a value qualifies as boolean, ensuring reliable predicate results in functional-style command compositions.[91] Prolog, as a declarative logic programming language, lacks an explicit Boolean type; instead, truth is embodied in query resolution, where goals succeed (true) by unifying facts and rules or fail (false) otherwise, as in negation-as-failure semantics.[92] Boolean queries, such as ?- member(X, [a,b,c]), X = a., yield success with bindings or failure without, driving backtracking in a purely logical framework.[92]

Database and Query Languages

In relational database management systems, the BOOLEAN data type, formalized in the SQL:1999 standard (ISO/IEC 9075), represents logical values with three states: TRUE, FALSE, and NULL, where NULL denotes UNKNOWN to handle incomplete or missing data. This three-valued logic extends classical Boolean algebra, ensuring that operations involving NULL propagate uncertainty; for instance, TRUE AND UNKNOWN evaluates to UNKNOWN, while FALSE AND UNKNOWN yields FALSE, and TRUE OR UNKNOWN results in TRUE.[93] SQL operators such as AND, OR, and NOT follow these rules, with NULL comparisons (e.g., value = NULL) always returning UNKNOWN rather than TRUE or FALSE, necessitating explicit checks like IS NULL for accurate querying.[93] In visualization tools like Tableau, boolean values (True or False) are integral to calculated fields, enabling conditional logic through functions such as IF, AND, and OR, which return boolean results for filtering datasets or driving VizQL expressions that generate visual queries.[94] Boolean fields serve as efficient filters in views, where True/False states simplify user interactions, such as toggling data inclusion without numerical conversions, enhancing performance in dynamic dashboards.[94] NoSQL databases handle booleans more flexibly, often embedding them directly in document structures without a dedicated type. In MongoDB, for example, boolean fields store true or false as JSON primitives within BSON documents, allowing queries like {status: true} to match exact values or use operators like $eq for precise filtering, though absent fields differ from explicit false.[95] For optimization, boolean columns in systems like PostgreSQL are stored compactly using 1 byte per value, supporting efficient indexing; low-cardinality booleans benefit from bitmap index scans, where the query planner combines multiple such indexes into a bitmap for faster heap retrieval during selective queries.[96]

References

User Avatar
No comments yet.