An operator is a symbol that denotes or performs a mathematical or logical operation. An operator, like a function, returns a result. For example, the + operator adds two numbers . The arguments to the operator are called operands. Operators are assigned a precedence. An operator with a precedence of 1 is said to have a high precedence level; it is, after all, number 1!
In OOo Basic (see Table 12 ), operators are evaluated from left to right with the restriction that an operator with a higher precedence is used before an operator with a lower precedence. For example, 1 + 2 * 3 evaluates to 7 because multiplication has higher precedence than addition. Parentheses may be used to modify the order of evaluation. For example, (1+2) * 3 evaluates to 9 because the expression inside the parentheses is evaluated first.
Precedence | Operator | Type | Description |
---|---|---|---|
1 | NOT | Unary | Logical or bitwise NOT |
1 | - | Unary | Leading minus sign, negation |
1 | + | Unary | Leading plus sign |
2 | ^ | Binary | Numerical exponentiation |
3 | * | Binary | Numerical multiplication |
3 | / | Binary | Numerical division |
4 | MOD | Binary | Numerical remainder after division |
5 | \ | Binary | Integer division |
6 | - | Binary | Numerical subtraction |
6 | + | Binary | Numerical addition and string concatenation |
7 | & | Binary | String concatenation |
8 | IS | Binary | Do two objects reference the same object? |
8 | = | Binary | Equals |
8 | < | Binary | Less than |
8 | > | Binary | Greater than |
8 | <= | Binary | Less than or equal to |
8 | >= | Binary | Greater than or equal to |
8 | <> | Binary | Not equal |
9 | AND | Binary | Bitwise for numerics and logical for Boolean |
9 | OR | Binary | Bitwise for numerics and logical for Boolean |
9 | XOR | Binary | Exclusive OR, bitwise for numerics and logical for Boolean |
9 | EQV | Binary | Equivalence, bitwise for numerics and logical for Boolean |
9 | IMP | Binary | Implication bitwise for numerics and logical for Boolean. |
Compatibility | Visual Basic uses a different precedence for operators - for example, numerical exponentiation and negation are switched, as are integer division and remainder after division. |
The word "binary" means something made of or based on two things. "Unary" means something made of or based on one thing. A binary operator, not to be confused with a binary number, is placed between two operands. For example, the addition operator uses two operands with 1+2. In OOo Basic, binary operators are always evaluated from left to right based on operator precedence. A unary operator requires one operand that is placed directly to the right of the operator. For example, - (1 + 3). By necessity, a series of unary operators are evaluated right to left. For example, + - (1+3) must evaluate the rightmost negation operator first, returning a value of -4.
Mathematical operators can be used with all numerical data types. When operands of different types are mixed, a conversion is made to minimize the loss of precision. For example, 1 + 3.443 causes a conversion to a floating-point number rather than a conversion to an Integer. If the first operand is a number and the second operand is a string, the string is converted to a number. If the string does not contain a valid numerical value, a zero is returned and no error is generated. Assigning a string directly to a numeric variable, however, always assigns the value zero and no errors are generated. See Listing 30 .
Dim i As Integer i = "abc" 'Assigning a string with no numbers yields zero not an error Print i '0 i = "3abc" 'Assigns 3, automatically converts as it can. Print i '3 Print 4 + "abc" '4
OOo Basic tries to automatically convert types. No errors are generated when a string is used where a number is required. This is discussed in depth later.
OOo Basic allows unary operators to have spaces between the operator and the operand (see Table 5). Unary operators also have the highest precedence and are evaluated from right to left. A leading plus sign is arguably useless -it emphasizes that a constant is not negative but is otherwise effectively ignored. A leading minus sign indicates numeric negation.
Warning | The standard mathematical precedence rules give exponentiation higher precedence than negation. |
Numerical exponentiation supports integer and floating-point exponents. The exponentiation operator can operate on a negative number only if the exponent is an integer.
result = number^exponent
A positive integer exponent has a conceptually simple representation. The number is multiplied by itself exponent times. For example, 2^4 = 2 * 2 * 2 * 2. See Listing 31 .
Sub ExampleExponent Print "2^3 = " & 2^3 REM 2*2*2 = 8 Print "3^2 = " & 3^2 REM 3 *3 = 9 Print "-3^2 = " & -3^2 REM (-3) * (-3) = 9 Print "2^3^2 = " & 2^3^2 REM 2^3^2 = 8^2 = 64 Print "4^0.5 = " & 4^.5 REM 2 Print "4^-0.5 = " & 4^-.5 REM .5 End Sub
Warning | OOo Basic evaluates multiple exponents (2^3^4) left to right ((2^3)^4), while standard mathematical precedence evaluates right to left. (2^(3^4)). |
Multiplication and division have the same precedence. See Listing 32 .
Sub ExampleMultDiv Print "2*3 = " & 2*3 REM 6 Print "4/2.0 = " & 4/2.0 REM 2 Print "-3/2 = " & -3/2 REM -1.5 Print "4*3/2 = " & 4*3/2 REM 6 End Sub
The MOD operator is also called "remainder after division." For example, 5 MOD 2 is 1 because 5 divided by 2 is 2 with a remainder of 1. All operands are rounded to Integer values before the operation is performed. See Listing 33 and Listing 34 as well as Figure 9 .
x MOD y = x - (y * (x\y))
REM x MOD y can also be written as REM CInt(x) - (CInt(y) * (CInt(x)\CInt(y))) REM CInt is used because the numbers must be rounded REM before the operations are performed. Sub ExampleMOD Dim x(), y(), s$, i% x() = Array (4, 15, 6, 6.4, 6.5, -15, 15, -15) y() = Array (15, 6, 3, 3, 3, 8, -8, -8) For i = LBound(x()) To UBound(x()) s = s & x(i) & " MOD " & y(i) & " = " & (x(i) MOD y(i)) & CHR$(10) Next MsgBox s, 0, "MOD operator" End Sub
Note | The operands are rounded to Integer values before the division is done. |
Regular division expects to divide a Double by a Double and it returns a Double as an answer. For example, 7.0 / 4.0 is 1.75. Integer division, on the other hand, expects to divide two Integers and it returns an Integer as an answer. For example, 7.2 \ 4.3 converts the operands to 7 \ 4 and then returns 1. The operands used with the Integer division operator are truncated to Integer values and then Integer division is performed. The result is a truncated result, not a rounded result. Listing 35 compares the difference between Integer division and regular division.
Sub ExamplelntDiv Print "5/2 = " & 5/2 REM 2.5 Print "5 = " & 5 REM 2 Print "5/3 = " & 5/3 REM 1.666666667 Print "5 = " & 5 REM 1 Print "5/4 = " & 5/4 REM 1.25 Print "5 = " & 5 REM 1 Print "-5/2 = " & -5/2 REM -2.5 Print "-5 = " & -5 REM -2 Print "-5/3 = " & -5/3 REM -1.666666667 Print "-5 = " & -5 REM -1 Print "-5/4 = " & -5/4 REM -1.25 Print "-5 = " & -5 REM -1 End Sub
Note | The operands are truncated to Integer values before the division is done. |
Addition and subtraction have the same precedence, which is higher than the string concatenation operator. Care must be taken while adding numerical values because the plus operator can also signify string concatenation. When the first operand for the plus operator is a number and the second is a string, the string is converted to a number. When the first operand for the plus operator is a string and the second is a number, the number is converted to a string.
Print 123 + "3" REM 126 (Numeric) Print "123" + 3 REM 1233 (String)
The string operator tries to convert the operands to strings if at least one operand is a string.
Print 123 & "3" REM 1233 (String) Print "123" & 3 REM 1233 (String) Print 123 & 3 REM Use at least one string or it will not work!
Mixing string manipulations and numerical manipulations may lead to confusing results, especially because string concatenation with the & operator has lower precedence than the + operator.
Print 123 + "3" & 4 '1264 Do addition then convert to String Print 123 & "3" + 4 '12334 Do addition first but first operand is String Print 123 & 3 + "4" '1237 Do addition first but first operand is Integer
Each logical operator asks a simple question and provides a True or False answer. For example, is it true that (you have money) AND (you want to purchase my book)? These types of operations are simple and are frequently used in OOo Basic. Less frequently used, and provided for completeness to keep the computing professionals happy, are the bitwise operators. Bitwise operators are not difficult, but if you don't understand them it isn't likely to affect your usage of OOo Basic. Table 13 illustrates the logical operators supported by OOo.
x | y | x AND y | x OR y | x XOR y | x EQV y | x IMP y |
---|---|---|---|---|---|---|
True | True | True | True | False | True | True |
True | False | False | True | True | False | False |
False | True | False | True | True | False | True |
False | False | False | False | False | True | True |
1100 | 1010 | 1000 | 1110 | 0110 | 1001 | 1011 |
A logical operator is usually thought to operate on True and False values. In OOo Basic, logical operators also perform bitwise operations on Integer values. This means that each bit of the first operand is compared to the corresponding bit in the second operand to form the corresponding bit in the result. For example, the binary operands 01 and 10 use the 0 from 01 and the 1 from 10 to produce the first bit of the result.
The unusual thing about logical and bitwise binary operators in OOo Basic is that their precedence is the same. In other languages, AND typically has greater precedence than OR.
Internally, the logical operators cast their operands to type Long. An unexpected side effect is that a floatingpoint operand is converted to a Long, which might cause numerical overflow. The conversion from a floating-point number to an integer number is done by truncating the value, not by rounding. The values chosen for True (-1) and False (0) allow this to work, but the return type with two Boolean operands is still sometimes of type Long (see Listing 36 ).
Sub LogicalOperandsAreLongs Dim v, bl As Boolean, b2 As Boolean bl = True : b2 = False v = (bl OR b2) Print TypeName(v) REM Long because operands are converted to Long. Print v REM -1 because the return type is Long. Print (b2 OR "-1") REM -1 because "-1" is converted to a Long. End Sub
For some logical expressions, not all operands need to be evaluated. For example, the expression (False AND True) is known to be False by looking at the first operand. This is known as " short-circuit evaluation." Sadly, this isn't available in OOo Basic; instead, all operands are evaluated.
Warning | OOo Basic does not support short-circuit evaluation, so (x <> 0 AND y/x > 3) results in a division-by-zero error when x is zero. |
The bitwise operators are all illustrated the same way. Two arrays are filled with Boolean values and two integers are given an Integer value.
xi% = 12 : yi% = 10 x() = Array(True, True, False, False) y() = Array(True, False, True, False)
The number 12 is represented in base 2 as 1100, which corresponds to the values in x(). The number 10 is represented in base 2 as 1010, which corresponds to the value in y(). The operator is then applied to "x(0) op y(0)", "x(1) op y(1)", "x(2) op y(2)", "x(3) op y(3)", and "xi op yi". The result is displayed in a message box. The integers are displayed as base 2 to emphasize that a bitwise operation is performed. Listing 37 demonstrates how an integer is converted to a stream of bits. This uses many techniques that are discussed later in this chapter.
REM Convert an Integer value to a string of bits REM x is the integer to convert REM n is the number of bits to convert REM This would be easier if I could shift out the lowest while REM retaining the sign bit of the number, but I cannot. REM I emulate this by dividing by two, but this fails for negative REM numbers. To avoid this problem, if the number is negative REM I flip all of the bits, which makes it a positive number and REM then I build an inverted answer Function IntToBinaryString(ByVal x%, ByVal n%) As String Dim b1$ 'Holds the 1 bit for positive numbers Dim b0$ 'Holds the 0 bit for positive numbers If (x >= 0) Then 'Not negative so the algorithm will work bl = "1" : b0 = "0" 'Use the standard bit values Else 'A negative number so x = NOT x 'Flip all of the bits. bl = "0" : b0 = "1" 'Invert what the bits are End If Dim s$ 'Accumulate bits as a string in s$ Do While n > 0 'n is the number of bits to return If (x AND 1) = 1 Then 'AND with 1 to find what the 1 bit is s = bl$ & s 'Bit 1 set so add a 1 (if x was negative add 0) Else s = b0$ & s 'Bit 1 clear so add a 0 (if x was negative add 1) End If x = x 'Integer division by 2 n = n - 1 'Decrement n by 1, just finished a bit. Loop 'Back to the top of the While IntToBinaryString = s 'Assign the return value to the Function End Function
Perform a logical AND operation on Boolean values and a bitwise AND on numerical values. Consider the phrase, "You can go to the movie if you have money AND if you have transportation." Both conditions must be true before you are able to go to the movie. If both operands are True then the result is True; otherwise the result is False. See Listing 38 and Figure 10 .
Sub ExampleOpAND Dim s$, x(), y(), i%, xi%, yi% xi% = 12 : yi% = 10 x() = Array(True, True, False, False) y() = Array(True, False, True, False) For i = LBound(x()) To UBound(x()) s = s & x(i) & " AND " & y(i) & " = " & CBool(x(i) AND y(i)) & CHR$(10) Next s = s & IntToBinaryString(xi, 4) & " AND " & IntToBinaryString(yi, 4) &_ " = " & IntToBinaryString(xi AND yi, 4) & CHR$(10) MsgBox s, 0, "Operator AND example" End Sub
Perform a logical OR operation on Boolean values and a bitwise OR on numerical values. Consider the phrase, "You can purchase that if you have cash OR your friend has cash." It does not matter who has cash. If either operand is True then the result is True; otherwise the result is False. See Listing 39 and Figure 11 .
Sub ExampleOpOR Dim s$, x(), y(), i%, xi%, yi% xi% = 12 : yi% = 10 x() = Array(True, True, False, False) y() = Array(True, False, True, False) For i = LBound(x()) To UBound(x()) s = s & x(i) & " OR " & y(i) & " = " & CBool(x(i) OR y(i)) & CHR$(10) Next s = s & IntToBinaryString(xi, 4) & " OR " & IntToBinaryString(yi, 4) &_ " = " & IntToBinaryString(xi OR yi, 4) & CHR$(10) MsgBox s, 0, "Operator OR example" End Sub
The XOR operator is called "exclusive or"; this is a question of nonequivalence. The result is True if the operands have different values. The result is False if both operands have the same value. A logical XOR operation is performed on Boolean values and a bitwise XOR is performed on numerical values. See Listing 40 and Figure 12 .
Sub ExampleOpXOR Dim s$, x(), y(), i%, xi%, yi% xi% = 12 : yi% = 10 x() = Array(True, True, False, False) y() = Array(True, False, True, False) For i = LBound(x()) To UBound(x()) s = s & x(i) & " XOR " & y(i) & " = " & CBool(x(i) XOR y(i)) & CHR$(10) Next s = s & IntToBinaryString(xi, 4) & " XOR " & IntToBinaryString(yi, 4) &_ " = " & IntToBinaryString(xi XOR yi, 4) & CHR$(10) MsgBox s, 0, "Operator XOR example" End Sub
The EQV operator is a question of equivalence: Are the two operands the same? A logical EQV operation is performed for Boolean values and a bitwise EQV on numbers. If both operands have the same value, the result is True. If the operands don't have the same value, the result is False. See Listing 41 and Figure 13 .
Sub ExampleOpEQV Dim s$, x(), y(), i%, xi%, yi% xi% = 12 : yi% = 10 x() = Array(True, True, False, False) y() = Array(True, False, True, False) For i = LBound(x()) To UBound(x()) s = s & x(i) & " EQV " & y(i) & " = " & CBool(x(i) EQV y(i)) & CHR$(10) Next s = s & IntToBinaryString(xi, 4) & " EQV " & IntToBinaryString(yi, 4) &_ " = " & IntToBinaryString(xi EQV yi, 4) & CHR$(10) MsgBox s, 0, "Operator EQV example" End Sub
The IMP operator performs a logical implication. A logical IMP operation is performed on Boolean values and a bitwise IMP on numbers. As the name implies, "x IMP y" asks if the statement that "x implies y" is a true statement. To help understand logical implication, define x and y as follows :
x = The sky is cloudy y = The sun is not visible If x Then y
If both x and y are true-the sky is cloudy and the sun is not visible-the statement can be considered true. This statement makes no claim about y if x is not true. In other words, if the sky is not cloudy, this statement does not imply that the sun is, or is not, visible. For example, it might be a clear night or (like a good computer geek) you might be inside a room without any windows . This explains why the entire statement is always considered valid when x is false. Finally, if x is true and y is not, the entire statement is considered false. If the sky is cloudy and the sun is visible, the statement cannot possibly be correct; a cloudy day could not imply that the sun is not visible. See Listing 42 and Figure 14 .
Sub ExampleOpIMP Dim s$, x(), y(), i%, xi%, yi% xi% = 12 : yi% = 10 x() = Array(True, True, False, False) y() = Array(True, False, True, False) For i = LBound(x()) To UBound(x()) s = s & x(i) & " IMP " & y(i) & " = " & CBool(x(i) IMP y(i)) & CHR$(10) Next s = s & IntToBinaryString(xi, 4) & " IMP " & IntToBinaryString(yi, 4) &_ " = " & IntToBinaryString(xi IMP yi, 4) & CHR$(10) MsgBox s, 0, "Operator IMP example" End Sub
The NOT operator performs a logical NOT operation on Boolean values and a bitwise NOT on numerical values. This means that "Not True" is False and "Not False" is True. For bitwise operations, a 1 becomes a 0 and a 0 becomes a 1.
Print NOT True REM 0, which is False Print NOT False REM -1, which is True Print NOT 2 REM -3, which took the bits 0010 to 1101
The comparison operators work with numerical, Date, Boolean, and String data types.
Print 2 = 8/4 AND 0 < 1/3 AND 2 > 1 '-1=True Print 4 <= 4.0 AND 1 >= 0 AND 1 <> 0 '-1=True
String comparisons are based on their internal representations as numbers and are case sensitive. The letter "A" is less than the letter "B". The uppercase characters are less than the lowercase letters .
Dim a$, b$, c$ a$ = "A" : b$ = "B" : c$ = "B" Print a$ < b$ 'True Print b$ = c$ 'True Print c$ <= a$ 'False
Bug | Some strange problems occur when all of the operands are string constants. If at least one operand is a variable, the expected results are achieved. |
Print "A" < "B" '0=False, this is not correct Print "B" < "A" '-1=True, this is not correct Print 3 = "3" 'False, but this changes if a variable is used
When variables are used rather than string constants, the numerical values are converted to string types for the comparison.
Dim a$, i%, t$ a$ = "A" : t$ = "3" : i% = 3 Print a$ < "B" 'True, String compare Print "B" < a$ 'False, String compare Print i% = "3" 'True, String compare Print i% = "+3" 'False, String compare Print 3 = t$ 'True, String compare Print i% < "2" 'False, String compare Print i% > "22" 'True, String compare
Tip | When comparing operands of different types, especially when mixing numeric and string types, it is safer to explicitly perform a type conversion. Either convert the string to a number or the number to a string. The functions to do this are discussed later. |
Compatibility | Visual Basic supports an Option Compare statement that controls how strings are compared. This is not compatible with OOo Basic. |