• No results found

Logical expressions

In document Quantum Vol1 (Page 44-59)

Logical expressions are used for comparing values, codes and variables.

Comparing values

Quick Reference

To compare the values of two arithmetic expressions, type:

arith_exp log_operator arith_exp

where log_operator is one of the operators .eq., .gt., .ge., .lt., .le. or .ne.

Values are compared when you need to check whether an expression has a given value — for example, did the respondent buy more than 10 pints of milk?

Values are compared by placing arithmetic expressions on either side of one of the following operators:

If the number of pints of milk that the respondent bought is stored in columns 114 and 115, the expression to check whether he bought more than ten pints would be:

c(114,115) .gt. 10

If the number in these columns is greater than ten the expression is true, otherwise it is false.

In chapter 4, ‘Basic elements’, we said that integer variables may take numeric values or the logical values true and false depending upon whether or not the value is zero. To check whether the respondent bought any packets of frozen vegetables, we can either write:

fveg .gt. 0

to check the numeric value of the variable fveg, or we can simply say:

fveg

.eq. Equal to

.gt. Greater than

.ge. Greater than or equal to

.lt. Less than

.le. Less than or equal to .ne. Not equal to / unequal to

to check whether the logical value of fveg is true. To check whether fveg is false (that is, zero), we would write:

.not. fveg

For further information about .not., see ‘Combining logical expressions’ later in this chapter.

Comparing data variables and data constants

In virtually every Quantum run you will want to check which codes occur in which columns. This is easily done using logical expressions. There are several forms of expression depending on whether you are checking a column or a field of columns.

Data variables

Quick Reference

To test whether a data variable contains at least one of a list of codes, type:

var_name’codes’

To test whether a data variable contains none of the listed codes, type:

var_namen’codes’

To test whether a data variable contains exactly the given codes and nothing else, type:

var_name = ’codes’

To test whether a data variable contains exactly the given letter and nothing else, type:

var_name = ’letter’

To test whether two data variables contain identical codes, type:

var_name1 = var_name2

To test whether a data variable contains codes other than those listed, type:

var_nameu’codes’

To test whether two data variables do not contain identical codes, type:

var_name1uvar_name2

To check whether a column or data variable contains certain codes, place the codes, enclosed in single quotes, immediately after the name of the column or data variable. For example:

c1’1’ c156’23’ brand’5’

The expression:

Cn’p’

checks whether a column (n) contains a certain code or codes (p). The expression is true as long as column n contains at least one of the given codes. It does not matter if there are other codes present since these are ignored.

For example, to check whether column 6 contains any of the codes 1 through 4 we would type:

c6’1/4’

The expression is true if c6 contains any of the codes 1, 2, 3 or 4 or any combination of those codes, regardless of what other codes may also be present. For instance:

----+----1 ----+----1 ----+----1 1 1 1 6 2 3 8 3 0 - 4

&

are true, but:

----+----1 5 7 9

-is false.

In our original example we chose the codes 1 through 4. You can, of course, use any codes you like and they may be entered in any order.

The opposite of cn’p’ is:

cnN’p’

which checks that a column does not contain the given code or codes. The expression is true as long as the column does not contain any of the listed codes.

For example:

c478n’5/7&’

is true as long as column 478 does not contain a 5, 6, 7 or & or any combination of them. A multicode of ‘189’ returns the logical value true, because it does not contain any of the codes

‘5/7&’ whereas a multicode of ‘1589’ makes the expression false because it contains a ‘5’.

The ‘=’ operator is used to check that the contents of a column are identical to either the given codes or the given letters.

The expression:

c312=’1/46’

is true as long as c312 contains all of the codes 1 through 4 and 6, and nothing else. The expression:

c142=’ ’

checks that column 142 is blank. The equals sign is optional when checking for blanks, so we could simply write:

c142’ ’

to check whether column 142 is blank.

The expression:

c124=’A’

checks that column 124 contains the letter A and nothing else.

The ‘=’ operator may also be used to compare the contents of two data variables. For example:

c56=c79

checks whether c56 contains exactly the same codes as c79. If so, the expression is true, otherwise it is false. If we have:

+----6----+ ... 1 1 5 5 the expression is true, but:

+----6----+ ... 1 1 5 5 9

yields the value false because column 79 contains a ‘9’ when column 56 does not.

If you have defined your own data variables, you could write a statement of the form:

brand1=c79

to check whether the data variable called brand1 contains the same codes as c79.

The opposite of ‘=’ is ‘U’ (unequal):

cnU’p’

This checks whether column n contains something other than just the code ‘p’. Suppose we have two sets of data:

----+----4 ----+----4 1 1

4 5 7 9 and we write:

c34u’7’

The expression is true for both sets of data. In the first example, the ‘7’ is multicoded with a ‘1’ and a ‘4’, while in the second example, column 34 does not contain a ‘7’ at all. The only time this expression is false is when column 34 contains a ‘7’ and nothing else.

Fields of data variables

Quick Reference

To test whether a field contains a given list of codes, type:

var_name(start,end) = $codes$

To test whether a field contains a given list of letters, type:

var_name(start,end) = $letters$

To test whether two fields contain identical strings, type:

var_name1(start1,end1) = var_name2(start2,end2)

To test whether the codes in one field differ from a given string, type:

var_name(start,end)u$codes$

To test whether the codes in one field differ from those in another, type:

var_name1(start1,end1)uvar_name2(start2,end2)

The contents of data fields must be enclosed in dollar signs with each code in the string referring to a separate column in the field. For instance, to check whether columns 47 to 50 contain the codes –, 6, 4 and 9 respectively we would type:

c(47,50)=$–649$

The only data for which this expression is true is:

+----5----+

-649

However, if our data read:

+----5----+

-529 164&

the expression would be false because all columns are multicoded.

In a similar way as you can test whether a field contains a given list of codes, you can also check whether a field contains a given list of letters. For example, to check whether columns 55 to 57 contained the string AAA, we would type:

c(55,57)=$AAA$

The only data for which this expression is true is:

+----5---+

AAA

All our examples have used columns, but the same rules apply to data variables that you define yourself. For example:

rating(1,4)=$1234$

checks whether the field rating1 to rating4 contains the codes 1, 2, 3 and 4 in that order. That is, it checks whether rating1 contains a 1, whether rating2 contains a 2, and so on.

When checking the contents of fields in this way, make sure that you enter as many columns as there are codes in the string (that is, five codes require five columns). The exception to this rule occurs when you are checking for blanks when the expression may be shortened to:

c(50,80)=$ $

This type of statement may also be used to compare two fields, to check whether the second field contains exactly the same codes as the first field. When you compare one field with another, Quantum takes each column in the first field in turn and looks to see whether the corresponding column in the second field contains exactly the same codes. For example, if the first column of the first field contains a code 1 and a code 2 and nothing else, then Quantum will check whether the first column of the second field also contains a code 1 and a code 2 and nothing else. If all columns of the second field are identical to their counterparts in the first field, then the expression is true;

otherwise it is false. Here is an example:

c(129,132)=c(356,359)

For this expression to be true, column 129 must contain exactly the same codes as column 356, column 130 must be exactly the same as column 357, and so on. Once again, the two expressions on either side of the equals sign must be the same length.

Comparisons of one data variable against another are concerned with columns and codes: they are not concerned with the arithmetic values of the codes in the fields as a whole.

If we have:

02 2 the expression:

c(24,25)=c(34,35)

is false because the string $02$ is not the same as the string $2$. If you want to compare fields arithmetically (for example, is 02 the same as 2) then you will need to use the .eq. operator:

c(24,25).eq.c(34,35)

to test whether the value in c(34,35) was equal to the value in c(24,25).

For further information about the .eq. operator, see ‘Comparing values’, earlier in this chapter.

To check whether the codes in one field do not match a given string or the codes in another field, we can use the u (unequals) operator:

c(m,n)U$codes$ cmUcn c(m,n)Uc(m1,n1)

If codes in the field c(m,n) do not match the given string or the codes in c(m1,n1) then the expression is true. If the two fields are identical, then the expression is false.

The comparison is of codes in columns, where the columns are compared on a one to one basis. It is not a comparison of a field with a numeric value, or of the numeric values in two fields. Numeric comparisons for inequality are written with the .ne. operator.

For further information about numeric comparisons, see ‘Comparing values’, earlier in this chapter.

Let’s look at an example of the unequals operator. The statement:

c(67,69)u$123$

is true at all times unless our data reads:

+----7----+

123

The expression:

c(67,69)uc(77,79)

is true as long as columns 67 to 69 differ by at least one code from columns 77 to 79. If our data is:

+----7----+----8 123 256

the expression is true because each of columns 77 to 79 differ from columns 67 to 69. Also, if we have:

+----7----+----8 123 123 5

the expression is true because column 77 is multicoded ‘15’. The only time the expression is false is when columns 67 to 69 are identical to columns 77 to 79.

Checking the arithmetic value of a field of columns

Quick Reference

To test whether a value in a field is within a specified range, type:

range(start,end,minimum,maximum)

Blanks at the start of the field cause this statement to give a false result. To ignore leading blanks, type:

rangeb(start,end,minimum,maximum)

The logical expression range checks whether the number in a field of columns is within a given range. If so, the expression is true, otherwise it is false. The format of this statement is:

range(start,end,min,max)

where start and end are column numbers and min and max are the range delimiters. For example, the statement:

range(137,139,100,150)

will return the value true if the number in columns 37 to 39 of card 1 is in the range 100 to 150.

It is important to remember that this statement is designed for use with purely numeric columns. Columns which contain blanks, multicodes or an ampersand (12 punch) automatically cause the statement to be false. The exception to this is a multicode of a digit and a minus sign (11 code) which converts the whole field to a negative number.

A variation of range is rangeb which allows columns to the left of the field to be blank if the number is right-justified in the field. In all other respects it is exactly the same as range. If our data is:

----+----2 123 6 the expression:

rangeb(17,18,1,10)

will be true because the string $ 6$ will be read as 6. With range the value would be false.

However, the expression:

rangeb(15,18,2000,3000)

returns false because of the blank in c17.

Combining logical expressions

Quick Reference

To combine logical expressions, type:

expression operator expression where operator is one of .or., .and., or .xor.

Two or more logical expressions may be combined into a single expression using the operators:

Any number of subexpressions may be combined to form a larger expression, but whether the result is true or false depends upon the values of the subexpressions and also upon the operators used to combine them.

.and. Both/all true.

.or. One or the other or both/all true.

.not. Negates (reverses) an expression.

The .and. operator requires that all the expressions preceding and following the .and. be true for the whole expression to be true. Thus, the statement:

int1.eq.9 .and. c116’1’

is true if the integer variable int1 has a value of 9 and column 116 contains a 1. If either subexpression is false, the whole expression is false too.

By comparison, the .or. operator requires that one expression or the other, or both, be true in order for the whole expression to be true.

c(249,251)=$159$ .or. numb(c132,c135) .gt. 4

For this expression to be true, columns 249 to 251 must contain nothing but a ‘1’, ‘5’ and ‘9’

respectively or the number of codes in columns 132 to 135 must be greater than 4. It is also true if both expressions are true. However, if both are false, the overall result is false.

Expressions are reversed (negated) simply by preceding them with the keyword .not. Although it is not wrong to use it with a single variable, it is more generally used to reverse an expression containing the keywords .and. and .or. Thus, it is not wrong to write .not.c15’1/5’ but it is much simpler to write this as c15n’1/5’.

Take care when using .not. with the .eq. operator. Statements of the form:

.not. c(1,3) .eq. 100

are incorrect and will not work. They should be written as either:

(.not.(c(1,3).eq.100))

with the expression to be reversed enclosed in parentheses, or, more efficiently, as:

(c(1,3).ne.100)

Any of the operators .and., .or, and .not. may appear in a statement more than once, as long as you use parentheses to define the order of evaluation.

For example:

(c15’1/47’ .or. c16’3579’) .and. c22’&’

causes Quantum to check whether the .or. condition is true before dealing with the .and. Suppose our data is:

----+----2----+

13 &

79

The first expression (c15’1/47’) is true because column 15 contains a 1 and a 7 and the second expression (c16’3579’) is also true since the codes it contains are amongst those listed as acceptable. Thus, the .or. condition is true. Column 22 contains an ampersand so the last expression is also true, therefore the expression as a whole is true regardless.

If both expressions in the parentheses were false, the whole expression would be false.

.not. with .and. and .or.

When you use .not. with expressions in parentheses, be very careful that what you write is what you mean. Let’s take the conditions male and married and forget about columns and codes for the minute. The condition:

(Male .and. Married)

refers only to married men. The opposite of this is:

.not. (Male .and. Married)

which refers to unmarried men and all women. This can also be written as:

.not. Male .or. .not. Married

The first .not. collects all the women, the second collects everyone who is not married (for example, single, widowed, and so on), and together they collect people who are female and unmarried. We use .or. instead of .and. here because the latter will gather unmarried women but will ignore the unmarried men and married women.

Reversing .or. expressions works in exactly the same way. The expression:

(Male .or. Married)

means anyone who is Male, or anyone who is Married, or anyone who is Male and Married. The opposite of this is:

.not. (Male .or. Married)

which means anyone who is not Male or is not Married or is not both; that is, anyone who is a woman and is unmarried. This can be written as:

.not. Male .and. .not. Married Thus, we can summarize, as follows:

Positive Negative Is the same as

(A .and. B) .not. (A .and. B) .not. A .or. .not. B (A .or. B) .not. (A .or. B) .not. A .and. .not. B

Here is an example using columns and codes:

.not. (c(135,137)=$519$ .or. c160’6/0’) If our data is:

3----+----4----+----5----+----6----+

519 1 9 &

the expression is true because c(135,137) do not contain just the codes 5, 1 and 9 (c135 is multicoded), and c160 does not contain any of the codes 6 through 0. The expression will only be false if:

• column 135 contains a 5 only, column 136 contains a 6 only and column 137 contains a 9 only, and

• column 160 contains any of the codes 6 through 0, either singly or as a multicode. We could therefore write the expression as:

.not. c(135,137)=$519$ .and. .not. c160’6/0’

Comparing variables and arithmetic expressions to a list

Quick Reference

To compare the value of a variable or an arithmetic expression to a list of numbers, type:

item .in. (value1,value2, ... )

in the edit section. Ranges of numbers may be entered in the list as start:end. If the item is a reference to a field containing blanks, enter the values as strings of codes enclosed in dollar signs.

From time to time you may need to check whether a variable or arithmetic expression has one of a given list of values. For example, if the questionnaire codes brands of frozen vegetables as 3-digit codes into columns 145 to 147 we might want to check that only valid codes appeared in this field.

This is achieved using the logical expression .in. as follows:

variable-name .in. (list) or arithmetic-exp .in. (list)

where variable-name is that of the variable to be checked and list is a list of permissible values.

The arithmetic expression is an expression consisting of data or integer variables, arithmetic operators and integer values as described earlier in this chapter. If the variable or arithmetic expression has one of the listed values, the expression is true, if not, it is false.

The left-hand side of the expression may contain integer variables, columns or data variables containing whole numbers, or expressions using these types of variables. If it is a data variable, then the list may contain codes enclosed in dollar signs. Quantum will then compare the codes in the data variable with the codes inside the dollar signs. We could therefore check that the frozen vegetables have been coded correctly by keying in a statement which says:

c(145,147) .in. ($205$,$206$,$207$,$210$,$215$,$220$)

Quantum will flag any records in which c(145,147) does not contain exactly 205, 206, 207, 210, 215 or 220 (that is, three single-coded columns) as incorrect.

If the data variable contains a valid positive or negative whole number, then the list may also contain such values. Ranges of values may be entered in the form min:max, where min is the lowest acceptable value and max is the highest. Since the frozen vegetables have numeric codes, we could write the expression as:

c(145,147) .in. (205:207,210,215,220)

Any columns in the field which contain non-numeric data (for example, multicodes) will be flagged as incorrect, as will any which contain values which do not match the specification.

Sometimes, though, the codes and numbers will not be interchangeable. If you have 2-digit codes in a 3-column field, the statement:

c(206,208) .in. ($ 10$,$ 11$,$ 12$,$ 13$) is not the same as:

c(206,208) .in. (10:13)

unless column 206 is always blank. If the 2-digit codes have been padded on the left with zeros instead of blanks (that is, 010, 011) or if they all start in column 206 (that is, $10 $, $11 $), then the first expression will be false, even though the second one will still be true.

For a fuller explanation of the difference between codes and numbers, see the earlier sections of this chapter.

If the left-hand side of the expression is an integer variable or an arithmetic expression, the list may contain positive or negative whole numbers:

total .in. (100,200,500:1000)

Lists may contain up to 247 values or codes, which may be entered in any order. In our examples,

Lists may contain up to 247 values or codes, which may be entered in any order. In our examples,

In document Quantum Vol1 (Page 44-59)