Sunday, October 19, 2008

Inf, Nan; Relational & Logical Operators and Find


These are some last set of expressions/operators that we need to familiarize ourselves with before we get to the discussion of programming and the use of M-files in MATLAB

Inf, Nan and eps

Infinity (+ or -) in MATLAB is represented by inf. This may happen more often you can think (for example, when there is stagnant data for a variable or there are data repetitions, some samples may show a zero variance, which in turn can result in 1/0 situations when you are finding correlations. 

Contrary to inf, NaN are 'quantities' which MATLAB throws up when a result is neither a number or infinity (e.g. an inf / inf situation). From my experience, NaN is most useful in pre-allocation, when you do not know the exact size of a matrix, but have some idea of the maximum. More on this later when we discuss pre-allocation and vectorization. 

Like all numeic software, MATLAB too has limits to how big/small numbers it can deal with.In MATLAB numbers larger than 1.7977e+308 (realmax) are taken to be Inf, and numbers smaller than 2.2251e-308 (realmin) are taken to be -Inf. 

A related expressiion is eps - which, to quote MATLAB help, represents floating point relative accuracy. It is roughly equal to 2 ^ (-52), but may depend on the CPU and the OS used (my desktop gives 2.2204e-016). Any quantity less than eps is taken to be same as zero. The reason it's called relative accuracy can be best explained by an example (taken from Kevin's notes):

>> x = 1; 

>> x = x + eps/2;

% gives x = 1 (because eps/2 is less than eps)

>> x = x - 1

% so it gives 0

Now let's change x = 1 to x = 2.1, and do the same steps again. and you get

>> x

  4.4409e-016

The reason (or may be it would be better to use the word 'explanation'), is that while:

eps/1 > eps/2

eps/2.1 <  eps/2

To expland on this, let's write x + eps/2 

as 

x * (1 + eps/2*x)

Now only if eps/2*x  >  eps, the expression is evaluated as the finite (non-zero) number it is, otherwise it's taken to be zero.

A mere technical detail it may seem right now, but when one is dealing with big (or very small) numbers and doing extensive calculations, failure to understand the role of precision can result in errors and blow-ups.

Relational Operators

The order / comparison operators in MATLAB work the way do in maths. The obvious ones are:

= (equal; eq), 
~= (not equal; ne), 
> (greater than; gt)
< (less than; lt)
>= (greater than or equa to; ge),
<= (less than or equal to; le)

When the comparison is made between two scalars their use is obvious. When it's between a scalar and a matrix, each element of the matrix is compared against the scalar. Two matrices can be compared only when they have the same dimesion, and in that case the comparison is always between apples and apples and never between apples and oranges. Or, in a less flowery (fruity?) language, x(i, j) is compared against y(i, j), where i and j refers to the same row and column indices respectively. 

The use of relational operators is almost always in control loops (if-else, for-end etc.) to check whether a condition is satisfied (or not) and what to do if the condition is satisfied (and what if it's not). 

Logical Operators

& (and), | (or) and ~ (not) are the well known Boolean operators and they work as they do in basic Boolean algebra. Their use is exactly like the relational operators discussed above. Very often they are used in conjunction with the relational operators, if (a <> d) etc etc.

Now we discuss some 'commands in logic' - i.e. the MATLAB commands that work in the sense of logical operations. The most important ones are:

1. logical: is used to convert non-logical (numbers) to logical elements. Logical numbers can be thought of as switches which are either on (1) or off (0).  Also, they can be used to work like indicator functions. Let:

>> x = [1 2 3 4];
>> y = [1 1];

then, x(y) = [x(1) x(1)]

but x(logical(y)) = [x(1) x(2)]

because, although logical(y) returns [1 1], but these represents indicators (on or off) for the 'location' (first and second element). 

2. all: takes input as logicals (1 or 0) and returns 1 if all the elements of a row are on, otherwise 0. Result on a matrix is a row vector.

3. any: similar to all, but differs in that it returns 1 if any of the element of a row are on, otherwise 0. 

4. is*: represents a collection of questions that you can ask of an input, whether it is infinite, finite, NaN etc. etc. Output is a logical. The list, inter alia,  includes:

isnan(x): returns 1 for all the elements which are NaN, and 0 at others

isinf(x): returns 1 for all the elements which are Inf, and 0 at others

isfinite(x): returns 1 for all the elements which are not Inf (finite), and 0 at others: 

ischar(x): returns 1 if x is a character array, and 0 otherwise

isempty(x): returns 1 if x is an empty matrix, and 0 otherwise

isequal(x, y): returns 1 if all the elements of x and y are equal, and 0 otherwise (x and y must be of same size)

islogical(x): returns 1 if x is logical and 0 otherwise

isscalar(x): returns 1 if x is a scalar, and 0 otherwise

isvector(x): returns 1 if x is a vector and 0 otherwise

[NB: isnan(x) + isinf(x) + isfinite(x) always equals 1. Why?] 

There are other variants of is* too. Look for help on is* for more. 

Find

The find command is so useful it deserves special mention. Although it is not one of the logical commands itself, it takes logical inputs and returns matrix indices where the logical statement is true [ack: Kevin Sheppard]. For example:

[i, j] = find( x <  y ) returns indices (row and column index) of x wherever x is less than y. It works for both scalars and matrices in the same way as relational operators do. 

Note that just the command x  <  y returns output which are logical (1 or 0), which then are used by find to get the row and column index. Some more examples:

>> find(a > 5);

>> a(find(a>5)) = 0;

>> ind = (a == 1);

>> b = a(ind);

>> b = a(a == 1);

>> ind = find(a == 1);

>> a(find(a == 1)) = 2;

More on this as we go along. 

No comments: