Math is performed using the
expr argument1 argument2 ... argumentN
expr 5+5
expr "5+5"
expr {5+5}
Best practice is to use the last example where the arguments are wrapped in braces. This is for two reasons first, it is faster. Second, and perhaps more importantly, it prevents the Tcl compiler from performing the first round of substitution and leaves it up to the
set x 8
set y x
set z y
expr {$x+3}
expr {$$y+3}; #this command fails
expr $$y+3; #this command executes
expr $$$z+3; #this command fails
If you tried to run the above code you would have gotten an error when you hit the line
The previous examples using
set x [expr {5+5}]; #notice the brackets around the expr command
puts "\$x = $x"; #prints: $x = 10
puts "5+5 = [expr {5+5}]"; #prints: 5+5 = 10
puts {5+5 = [expr {5+5}]}; #prints: 5+5 = [expr {5+5}]
Notice that brackets must be used around the
puts "4*(2+3) = [expr {4*[expr {2+3}]}]"; #prints: 4*(2+3) = 20
Below is a table of all the mathematical operators in order of precedence. This table was copied from https://wiki.tcl-lang.org/page/expr (which has a lot of great resources for learning Tcl).
-, +, ~, ! | Unary operators; specifically a negation operation, a non-negation operation, a bit-wise NOT operation (every bit in the input value gets replaced by its inverse) and a logical NOT operation (non-zero maps to zero, and zero maps to one). |
** | Exponential. From Tcl 8.5 on. |
*, /, % | Multiplication, division |
+, – | Addition and subtraction. |
<<, >> | Left and right shift. Equivalent to multiplying or dividing by a suitable power of two, and then reducing the result to the range representable in an integer on the host platform. |
<, >, <=, >= | Ordering relations: less than, greater than, less than or equal, greater than or equal. These operations work on strings as well as numbers, but where string comparison is intended, it is advisable to use the dedicated string comparison operators or string compare or string equal instead, as those are more predictable in the case of a string that looks like a number. For example, string equal considers “6” and “06” to be different strings, but the |
==, != | Equality and inequality. These operations work on strings as well as numbers, but see the description equality operators for notes about string comparison. |
eq, | Since Tcl 8.4, these are string-comparison operators. “6” and “06”, as well as 1 and 1.0, will compare |
in, ni | Checks for the occurrence of an item in a list. New in Tcl 8.5. |
& | Bit-wise AND. A bit is set in the result when the corresponding bit is set in both the arguments. |
^ | Bit-wise exclusive OR. A bit is set in the result when the corresponding bit is set in precisely one of the arguments. |
| | Bit-wise OR. A bit is set in the result when the corresponding bit is set in either of the arguments. |
&& | Logical AND. The result is 1 when both of the arguments are true. and 0 otherwise. This operation is a short-circuiting operation, and will only evaluate its second argument when the first argument is non-zero. This includes the expansion of Tcl commands in square brackets. Where Tcl seems not to be behaving as describe here, see double substitution. |
|| | Logical OR. The result is 0 when both of the arguments are false, and 1 otherwise. This operation is a short-circuiting operation, and will only evaluate its second argument when the first argument is zero. Where Tcl seems not to be behaving as describe here, see |
x | If-then-else, as in C. x, y, and z are expressions. The result is y if x is true, and z otherwise. This operation is a short-circuiting operation: If x is true, z will not be evaluated, and if x is false, y will not be evaluated. Where Tcl seems not to be behaving as describe here, see double substitution. if performs just as well as this construct. The generated bytecode is identical. |
Exercise
In this exercise, we’re going to perform a simple magic trick.
- Pick a number between 1-20 and store the number in a variable called
favNum (favorite number) using the set command - Using the
expr command, add 1 to the number and store it in a new variable called favNumMod (favorite number modified)with the set command - Next, double favNumMod and store the result in favNumModD (the D is for double)
- Now add 4 to favNumModD and store the result in favNumFour
- Divide favNumFour by 2 and then subtract favNum from the result. Store the answer in a new variable called
result - Finally, print result using the puts command (e.g. puts “result = $result”)
I’m predicting the final answer you got was …. this is a tough one… 3! How did I do it? It’s magic. If you didn’t get 3, go back through the exercise and see what went wrong. You will always get 3 when doing this exercise regardless of the starting number. If you figured out the trick explain it in the comments!
Tip, if your having trouble you can print out the results of each step using puts. This is a common debugging step.
To help you out I’ll give an example of what the result of each step should look like using pseudocode (something written in code-like format but won’t actually run). I’ll use the number 4 as my starting point but you don’t have to.
- favNum = 4
- favNumM = 5
- favNumD = 10
- favNum4 = 14
- result = 14/2-favNum