# Booleans and Comparisons

### Booleans and Comparisons

A boolean is a value that can be only one of two things:

```zig
true
false
```

The boolean type in Zig is:

```zig
bool
```

You use booleans when a program needs to answer a yes-or-no question.

```zig
const is_ready: bool = true;
const is_empty: bool = false;
```

A boolean value is usually used with `if`, `while`, and other control-flow constructs.

```zig
if (is_ready) {
    // run this code only when is_ready is true
}
```

#### Boolean values

The simplest boolean values are written directly:

```zig
const a = true;
const b = false;
```

Zig can infer that both values are booleans.

You may also write the type explicitly:

```zig
const a: bool = true;
const b: bool = false;
```

A boolean is not an integer. This is important.

In C, numbers can often be used as conditions:

```c
if (1) {
    // true in C
}
```

Zig does not allow that style.

This is invalid Zig:

```zig
if (1) {
    // error
}
```

The condition must be a `bool`.

Correct Zig code says the condition directly:

```zig
const enabled = true;

if (enabled) {
    // ok
}
```

This avoids a common class of bugs. Zig does not treat `0` as false or `1` as true.

#### Comparisons

A comparison asks a question about two values and returns a boolean.

```zig
const result = 10 > 5;
```

Here, `result` is `true`.

Zig supports the usual comparison operators:

| Operator | Meaning |
|---|---|
| `==` | equal to |
| `!=` | not equal to |
| `<` | less than |
| `<=` | less than or equal to |
| `>` | greater than |
| `>=` | greater than or equal to |

Examples:

```zig
const a = 10;
const b = 20;

const x = a == b; // false
const y = a != b; // true
const z = a < b;  // true
```

Each comparison produces a `bool`.

#### Using comparisons with `if`

Comparisons are most often used inside `if`.

```zig
const std = @import("std");

pub fn main() void {
    const age = 20;

    if (age >= 18) {
        std.debug.print("adult\n", .{});
    } else {
        std.debug.print("minor\n", .{});
    }
}
```

Output:

```text
adult
```

The expression:

```zig
age >= 18
```

produces `true`, so the first branch runs.

#### Equality and assignment are different

Beginners often confuse these two operators:

```zig
=
==
```

Single equals means assignment.

```zig
var x = 10;
x = 20;
```

Double equals means comparison.

```zig
const same = x == 20;
```

In words:

```text
x = 20   means put 20 into x
x == 20  means ask whether x is equal to 20
```

This distinction is fundamental.

#### Boolean operators

You can combine booleans with boolean operators.

| Operator | Meaning |
|---|---|
| `and` | both conditions must be true |
| `or` | at least one condition must be true |
| `!` | not |

Example:

```zig
const age = 25;
const has_ticket = true;

const can_enter = age >= 18 and has_ticket;
```

`can_enter` is true only if both conditions are true.

```zig
const is_weekend = false;
const is_holiday = true;

const can_sleep_late = is_weekend or is_holiday;
```

`can_sleep_late` is true if either condition is true.

The `!` operator reverses a boolean:

```zig
const enabled = false;
const disabled = !enabled; // true
```

#### `and`

The `and` operator requires both sides to be true.

```zig
const a = true;
const b = true;
const c = false;

const x = a and b; // true
const y = a and c; // false
```

Truth table:

| Left | Right | Result |
|---|---|---|
| `false` | `false` | `false` |
| `false` | `true` | `false` |
| `true` | `false` | `false` |
| `true` | `true` | `true` |

Use `and` when all requirements must be satisfied.

```zig
if (username_ok and password_ok) {
    // login allowed
}
```

#### `or`

The `or` operator requires at least one side to be true.

```zig
const a = true;
const b = false;
const c = false;

const x = a or b; // true
const y = b or c; // false
```

Truth table:

| Left | Right | Result |
|---|---|---|
| `false` | `false` | `false` |
| `false` | `true` | `true` |
| `true` | `false` | `true` |
| `true` | `true` | `true` |

Use `or` when any one condition is enough.

```zig
if (is_admin or is_owner) {
    // access allowed
}
```

#### `!`

The `!` operator means not.

```zig
const ready = false;

if (!ready) {
    // runs when ready is false
}
```

Read `!ready` as “not ready.”

Another example:

```zig
const file_exists = true;
const missing = !file_exists; // false
```

#### Short-circuit behavior

`and` and `or` use short-circuit evaluation.

This means Zig may skip the right side if the result is already known.

For `and`, if the left side is false, the whole expression must be false.

```zig
const result = false and expensiveCheck();
```

Here, `expensiveCheck()` does not need to run.

For `or`, if the left side is true, the whole expression must be true.

```zig
const result = true or expensiveCheck();
```

Again, `expensiveCheck()` does not need to run.

This is useful when the second condition is safe only after the first condition succeeds.

```zig
if (index < items.len and items[index] == 10) {
    // safe to access items[index]
}
```

The array access happens only if `index < items.len` is true.

#### Comparing integers

Integer comparisons are straightforward:

```zig
const a: i32 = -10;
const b: i32 = 5;

const less = a < b; // true
```

Signed and unsigned integers should be compared carefully. A signed integer can be negative. An unsigned integer cannot.

If two values have different integer types, Zig may require you to convert one explicitly. This keeps the comparison clear.

```zig
const a: u32 = 10;
const b: u64 = 20;

const result = @as(u64, a) < b;
```

Here, `a` is converted to `u64` before comparison.

#### Comparing floats

Floating point comparisons work, but equality is dangerous because floats are approximate.

This is usually fine:

```zig
const temperature: f64 = 22.5;

if (temperature > 30.0) {
    // hot
}
```

This can be risky:

```zig
const x: f64 = 0.1 + 0.2;

if (x == 0.3) {
    // may not run
}
```

For floats, prefer comparing with a tolerance when testing equality:

```zig
fn nearlyEqual(a: f64, b: f64, tolerance: f64) bool {
    return @abs(a - b) < tolerance;
}
```

Then:

```zig
if (nearlyEqual(x, 0.3, 0.000001)) {
    // close enough
}
```

#### A complete example

```zig
const std = @import("std");

fn canEnter(age: u8, has_ticket: bool, banned: bool) bool {
    return age >= 18 and has_ticket and !banned;
}

pub fn main() void {
    const age: u8 = 21;
    const has_ticket = true;
    const banned = false;

    if (canEnter(age, has_ticket, banned)) {
        std.debug.print("entry allowed\n", .{});
    } else {
        std.debug.print("entry denied\n", .{});
    }
}
```

Output:

```text
entry allowed
```

The function:

```zig
fn canEnter(age: u8, has_ticket: bool, banned: bool) bool
```

takes three inputs and returns a boolean.

The return expression:

```zig
age >= 18 and has_ticket and !banned
```

means:

```text
age is at least 18
and the person has a ticket
and the person is not banned
```

All three must be true for entry to be allowed.

#### The main idea

Booleans represent truth values. Comparisons produce booleans. Boolean operators combine booleans.

Zig keeps this strict. Conditions must be real `bool` values. Integers, pointers, and other values are not automatically treated as true or false.

This makes control flow easier to read and reduces accidental bugs.

