Logical Type and Conditions

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the section bibliography.

Written against MATLAB R2026b. The sessions below were run in GNU Octave 11.3.0 (MATLAB code that Octave also accepts) and show Octave’s output. isapprox (R2024b) is not available in Octave and is checked against the R2026b documentation ("not run here"). The conditions of if and while follow the rules of the MATLAB documentation; Octave agrees on the cases shown.

The logical class holds true and false. It is what comparisons return, what masks are made of (see Indexing) and what if and while ultimately test. Operators on logical values are on Operators and Precedence; the control-flow statements themselves are on Control Flow.

The logical class

true and false are logical scalars; true(m,n) and false(m,n) build arrays. A logical value uses one byte, and arithmetic on it follows the numeric rules: true + true is 2, of class double. Many functions return logical results by convention: the relational operators, isempty, isnumeric, ismember, any, all, isequal, isnan.

logical(x) converts a numeric array: zero becomes false and every other value becomes true, including negative numbers and Inf. NaN cannot be converted and raises an error (Octave 11.3.0 prints invalid conversion from NaN to logical; MATLAB raises an error with the identifier MATLAB:nologicalnan, not run here).

t = true; f = false;
class(t), class(5>3)
x = [3 0 7];
logical(x)
try, logical([1 NaN]), catch err, disp(err.message), end
sum([true true false])
true + true
class(true + true)

Octave 11.3.0 output:

ans = logical
ans = logical
ans =

  1  0  1

invalid conversion from NaN to logical
ans = 2
ans = 2
ans = double

Keep masks in their own variables: arithmetic on a mask gives a double, and a logical array that receives a number through indexed assignment keeps its class, so the number is converted to true or false.

Reducing arrays: any, all, nnz, isequal

  • any(X) is true if any element is nonzero; all(X) is true if all are. For a vector they return a scalar; for a matrix they work down each column unless you give a dimension (any(X,2), all(X,"all")).

  • nnz(X) counts the nonzero (or true) elements: nnz(x>1) is the number of elements greater than 1.

  • isequal(a,b,...) is true if all the arrays have the same size and equal elements; it is one scalar answer, unlike a == b. isequaln treats NaN values as equal, which isequal does not.

x = [3 0 7];
any(x), all(x), any(x==0)
nnz(x>1)
isequal([1 2 3],[1 2 3]), isequal(NaN,NaN), isequaln(NaN,NaN)

Octave 11.3.0 output:

ans = 1
ans = 0
ans = 1
ans = 2
ans = 1
ans = 0
ans = 1

How if and while treat arrays

The condition of if and while is allowed to be an array. The block runs only if the condition is non-empty and all its elements are nonzero (true). So if [1 1 1] runs, if [1 0 1] does not, and if [] does not.

if [1 1 1], disp('all nonzero'), end
if [1 0 1], disp('shown'), else, disp('not all'), end
if [], disp('shown'), else, disp('empty is false'), end

Octave 11.3.0 output:

all nonzero
not all
empty is false

This rule is the source of a classic bug. if x == y with two vectors is true only if every element is equal and, if the sizes differ (and are not compatible), is an error. if x with an array that contains a zero silently takes the else branch. And if [] is false, so a condition that comes from a search which found nothing (if find(x > 10)) is false for an empty result, which may or may not be the intent. Write the intention explicitly: if all(x(:) > 0), if any(x(:) > 10), if isempty(r), if isequal(a,b). To combine scalar conditions use the short-circuit operators && and ||, which require scalar operands (see Operators and Precedence).

Masks as numbers and ismember conditions

A logical mask can be summed (sum(mask) counts the true elements, as does nnz), averaged (mean(mask) is the fraction), and multiplied (x .* mask zeroes the unselected elements, which is a loop-free way to apply a condition). A mask can also index: x(mask).

ismember(a, S) is the condition for membership: it returns a logical array with the size of a that tells for each element whether it appears in the set S. It handles numbers and text (ismember("Dirichlet", ["Dirichlet" "Neumann" "Periodic"]), where the heatflow boundary kinds are the set).

ismember(3, [1 3 5])
ismember([1 2 3],[2 3])

Octave 11.3.0 output: ans = 1, and 0 1 1.

Comparing floating-point numbers

== on floating-point values tests for exact equality, so values that should be equal mathematically often differ in the last bits.

0.1+0.2 == 0.3
abs((0.1+0.2) - 0.3) < 1e-12
abs((0.1+0.2) - 0.3) <= eps(0.3)
a = 5; b = 5.0000000001;
abs(a-b) <= 1e-8*max(abs(a),abs(b))

Octave 11.3.0 output:

ans = 0
ans = 1
ans = 1
ans = 1

Use a tolerance that fits the problem: an absolute tolerance when values are near a known scale, a relative tolerance (a multiple of eps(x), the spacing at x) otherwise, and often both. Since R2024b the function isapprox does this: TF = isapprox(A,B) returns a logical array, true where elements are within the default relative and absolute tolerances, both 1e-15 (5e-7 if either input is single). isapprox(A,B,tol) takes the tolerance level "verytight", "tight", "loose" or "veryloose", and name-value arguments such as RelativeTolerance and AbsoluteTolerance set them explicitly (when only the relative tolerance is given, the absolute tolerance is 0). The inputs must have the same or compatible sizes, and NaN values are not considered approximately equal. Not run here; for code that must run before R2024b, write the explicit comparison above. The reference page for isapprox shows sin(3/4*pi) == 1/sqrt(2) is false but isapprox of the two is true.

Pitfalls

  • if x == y on arrays means all elements equal; use isequal when you mean whole-array equality.

  • An empty condition is false: if find(...) and if [].

  • == on floating-point values.

  • logical(NaN) is an error.

  • Comparing text with ==: for character vectors it compares element by element (and fails on different lengths); use strcmp or isequal (see Strings and Character Arrays).

  • Using & and | where && and || are needed for scalar conditions, and the reverse for arrays.

  • any/all of a matrix work column-wise.

Where older books differ

Older books present any, all and find as the tools for conditions and rarely mention isequaln, ismember with strings, or isapprox (R2024b). They compare floating-point numbers with a hand-written tolerance, which is still correct. The rule for array conditions in if has not changed.