A conditional branch statement allowing for execution of specific program segments only when a condition is logically "true".
See Remarks for comparisons of floating-point values.
If condition [Then] // program segment [Else If condition // program segment] [Else // program segment] EndIf
If condition Then statement [If | Else....]
Condition:any numeric, logic or string condition
The If...EndIf statement is, in addition to Select...Case, the most important command for controlling the program flow. The program segment after an If...EndIf statement will be executed if, and only if, the condition immediately following the If is logically True. Otherwise, the control is passed to an Else...If or Else within the same If...EndIf structure. If there are no Else...If or Else, a branch is performed to the statement immediately after the next EndIf. The following structure is an exclusive structure.
Dim a% = 10
If a% <> 0 Then
Print "a% <> 0"
Else
Print "a% = 0"
EndIf
This means that the test, if the condition a% <> 0 is logically true, will be performed first. If it is, the first program segment is executed and a branch to the statement following the EndIf is taken. If the condition is logically false, the program segment after Else is executed and a branch to the statement following the EndIf is taken. In no case will both program segments be executed.
This can be extended to an array of exclusive tests:
If Mod(42, 4) <> 0
Print "42 is not fully divisible by 4"
Else If Mod(42, 5) // means: <> 0
Print "42 is not fully divisible by 5"
Else If Mod(42, 8)
Print "42 is not fully divisible by 8"
Else If Mod(42, 9)
Print "42 is not fully divisible by 9"
Else
Print "42 is fully divisible by 4,5,8 and 9"
EndIf
Gives only '42 is not fully divisible by 4', because the very first condition is logically true. The first condition in the condition list is logically true causes the execution of the first program segment, and then a branch to the statement immediately after EndIf. This is irrespective of whether only one, several or all conditions in the condition list are logically true.
If there is only one condition it is possible to shorten the If...Endif structure to one line simply using If...Then; this simpler structure can also be augmented by one or more Else[..If] conditions as in the above examples, although the If...Endif is cleaner and easier to read and debug if more than one Else condition is added. Finally, it is possible to add an additional If...Then statement on the same line which is only enacted if the first condition is true. Examples of these different forms are below:
Local a% = 12, b$
// Simple If...Then statement
If a% < 20 Then b$ = "a% is less than 20"
Print b$
// If...Then...Else
If a% < 10 Then b$ = "a% is less than 10" Else b$ = "a% is greater than or equal to 10"
Print b$
// If...Then...Else If
If a% < 10 Then b$ = "a% is less than 10" Else If a% < 25 Then b$ = "a% is less than 25"
Print b$
// If...Then...If...Then
If a% < 20 Then If a% > 10 Then b$ = "a% is less than 20 but greater than 10"
Print b$
The last form is useful when dealing with Missing values in And statements as shown below:
Local a As Variant = Missing
If Not IsMissing(a) And a > 6 Then Print "a is greater than six" // Returns 'Variant Type' error
If Not IsMissing(a) Then If a > 6 Then Print "a is greater than six" // No error
To GFA-BASIC 32 any value that is not 0, is true. Likewise, the value 0 represents false. The condition If 1, therefore, will always evaluate to true, and If 0 always evaluate to false. When you want to test if a condition is true, you can simply include the expression:
If a$ [Then]
This expression evaluates to nonzero (true) when Len(a$) > 0, that is, when a$ contains any data.
NOTE: Be aware that, very rarely, there is a problem with Boolean variables - see here for more information.
If you want to test whether two conditions are true, you can use the logical AND operator &&. The condition is evaluated form left to right. To evaluate to true both conditions must be true. When the first condition is false, the second isn't evaluated.
If Len(a$) && height => 100
This expression evaluates to true when a$ contains data and the height variable is greater or equal to 100.
Note Do not confuse GFA-BASIC 32's logical AND operator && with the bitwise AND operator And or %&. The && operator evaluates two Boolean (true or false) expressions to produce a true or false result. The bitwise %& (And) operator, on the other hand, works bits (1's and 0's). Would the && operator be replaced by And, then both expression are evaluated to be And-ed. Then the result of the bitwise And operation is tested for true or false.
Dim a% = 10
If a% = 0 && ff() Then Print "Only one evaluated"
If a% = 0 And ff() Then Print "Both evaluated"
Function ff() As Int
Debug "ff"
Return 1
EndFunction
To test whether either of two conditions is true (or if both are true), use GFA-BASIC 32's logical OR operator ||. The condition is evaluated form left to right. To evaluate to true only one of the conditions must be true. When the first condition is true, the second isn't evaluated.
If a% = 0 || ff() Then Print "Both evaluated"
If a% || ff() Then Print "Only one evaluated"
The logical OR operator || is not the same as the bitwise OR operator Or, |, or %|. Replacing || with Or would first evaluate both conditions, which are then bitwise Or-ed. Then the result of the bitwise or operation is tested for true or false.
If a% Or ff() Then Print "Both evaluated"
Floating-point consistency when comparing floating-point values.
You might want to select the "Improve Floating-point consistency" checkbox in the Compiler tab of the Properties dialog. This options makes sure that before the CPU processes a floating-point value, the value is (re)read from memory (= variable). This is important, because the CPU works with 80-bit floating point values, where variables hold 64-bit values. Out of efficiency reasons the compiler always tries to use current value in the processor register in the next step as well (speed optimization). The following example demonstrates this. The If condition uses the result of d# = a#/b# that is currently in the CPU, which is a 80-bit value. The comparison with the value in c# is always false, because this is 64-bit floating-point value.
Dim a# = 2, b# = 3, c#, d#
c# = a# / b#
d# = a# / b#
If d# = c# Then Print "Eq"
It is important to get the correct value in the CPU registers before making a comparison. Checking the "Improve floating-point consistency" box is one option. However this influences all floating-point operations and might decrease efficiency.
Another option is to force a reload of the value from d# in the comparison. This loads a 64-bit value into the register and the comparison with c# will be correctly evaluated. To force a reload the processor must be cleared, which is easily done with ~0.
Dim a# = 2, b# = 3, c#, d#
c# = a# / b#
d# = a# / b#
~0 ' clear processor
If d# = c# Then Print "Eq"
~0 is translated in the assembler instruction sub eax, eax. The value is reloaded from d#.
It is sometimes possible to include the If...Then...Else combination on one line as follows:
Local a% = 10, b% = 5
If a% = 9 Then a% = 20, b% = 10 Else a% = 9, b% = 15
Print a%, b%
In this case, Endif is superfluous to requirements and should not be used.
However, with some commands such as Print and when Functions are invloved, this structure throws up an error. Hence...
Local a% = 10, b% = 5
If a% = 9 Then Print "TRUE" Else Print "FALSE"
...will be reformatted by the IDE and result in an error. To get around this, you can use the ':' separator as follows:
Local a% = 10, b% = 5
If a% = 9 Then Print "TRUE" : Else : Print "FALSE"
These errors occur as the 'Then' keyword is a late addition to GFA and the IDE seems not to have been fully edited to accomodate it.
{Created by Sjouke Hamstra; Last updated: 25/07/2020 by James Gaite}