Summary edit
expr - Evaluate an expressionSynopsis edit
expr arg ?arg arg ...?Documentation edit
Description edit
[expr] implements a mini language that has a syntax separate from the Tcl syntax. It supports some of the same constructs as Tcl, such as variable substitution, command substitution, and braces. It adds additional syntax for mathematical operators and functions, and unlike Tcl, does not accept character strings that are not enclosed in double quotes or brackets.[expr] conditions (e.g. [if] or [while]) take 0 to mean false and all other numbers to mean true. In addition, the following string constants can be used:- true, on, yes
- false, off, no
Beware that if you need code to run in Tcl releases as old as 8.3, you have to quote these if you use them directly as constants, as Donald Porter noted: [expr] tries to interpret "bare" strings as function names, such as cos($x). You must quote the string "true". Then it behaves as you expect in 8.3.3.Refer to the Operands section of the expr man page
for the syntax rules.Usage edit
[expr] concatenates each arg (adding separator spaces between them), evaluates the result as a Tcl expression, and returns the value. The operators permitted in Tcl expressions include most of the operators permitted in C expressions and a few aditional ones, and they have the same meaning and precedence as the corresponding C operators. Expressions almost always yield numeric results (integer or floating-point values). For example, the expression:set val1 8.2
set val2 6
expr {$val1} + ${val2}evaluates to 14.2.This is an equivalent way of writing the previous [expr] command:expr {$val1+$val2}Any argument that can be interpreted in some way, e.g., variable or a command expansion, should be enclosed in brackets. This allows the [expr] command to do the interpretation, rather than having the caller interpret the arguments before handing them off to [expr]. See below for more details.Tcl expressions differ from C expressions in the way that operands are specified. They also include some non-numeric operators for strings (comparison) and lists (membership).Operators edit
Note that many operators have command-equivalents in the namespace ::tcl::mathop from Tcl 8.5 onwards.[The term mathop is a misnomer, since some of the operators included in this namespace are string, rather than math, oriented...]The [expr] operators, in order of precedence (tightest-binding to least-tight binding), are:| - + ~ ! | Unary operators; specifically a negation operation, a non-negation operation (I see little point in this one), 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.) |
| * / % | Multiplication, division and integer remainder (see fmod() below.) |
| + - | 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.) Note that these operations work on strings as well as numbers, but you are probably better off testing the result of string compare instead as that is more predictable in the case of a string that looks like a number. |
| == != | Equality and inequality. Note that these operations work on strings as well as numbers, but you are probably better off testing the result of string equal instead as that is 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 [expr]'s == considers them to be equivalent numbers. |
| eq ne | (2004-07-08 added): From Tcl 8.4 on. The same as before, but arguments only strings. Will find "6" and "06" (as well as 1 and 1.0) to be different. |
| ** | exponential. From Tcl 8.5 on |
| in ni | Item (argument 1) in/not in list (argument 2). 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 a one (true) when both of the arguments are non-zero (true), and zero (false) otherwise. Note that 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, but this delay in evaluation only occurs if the whole expression is enclosed in curly braces. |
| || | Logical OR. The result is a zero (false) when both of the arguments are zero (false), and one (true) otherwise. Note that this operation is a short-circuiting operation, and will only evaluate its second argument when the first argument is zero. This includes the expansion of Tcl commands in square brackets, but this delay in evaluation only occurs if the whole expression is enclosed in curly braces. |
| x?y:z | If-then-else, as in C (where x,y,z are expressions). If the value x is non-zero (true) then the expression y is evaluated to produce the result, and otherwise the expression z is evaluated to produce the result. Note that this operation is a short-circuiting operation, and will not evaluate expression y if x is zero (false) and will not evaluate expression z if x is non-zero (true). This includes the expansion of Tcl commands in square brackets, but this delay in evaluation only occurs if the whole expression is enclosed in curly braces. It is usually clearer and easier to maintain (and no slower - the generated bytecode is identical) to use the Tcl if command instead of this. |
Functions edit
See the mathfunc man page, listed above, for the Tcl 8.5 man page information on [expr] builtin functions.builtin
- abs(x)
- Absolute value (negate if negative.)
- acos(x)
- Inverse cosine (result in radians.)
- asin(x)
- Inverse sine (result in radians.)
- atan(x)
- Inverse tangent (result in radians.)
- atan2(y,x)
- Inverse tangent. Can handle cases which plain atan() can't (due to division by zero) and has a larger output range (result in radians.)
- bool(x)
- Accept any numeric value or string (acceptable to string is boolean), and return the corresponding boolean value 0 or 1
- ceil(x)
- Ceiling (defined over floating point numbers.) If the input value is not a whole number, return the next larger whole number. Surprise: The return value is a float, not an integer.
- cos(x)
- Cosine (input in radians.)
- cosh(x)
- Hyperbolic cosine.
- double(x)
- Convert number to floating point.
- entier(x)
- Take any numeric value and return the integer part of the argument, as an unlimited value string
- exp(x)
- Exponential function. Returns e**inputValue (using the FORTRAN-style notation) where e is the base of natural logarithms.
- floor(x)
- Floor (defined over floating point numbers.) If the input value is not a whole number, return the next smaller whole number. Surprise: The return value is a float, not an integer.
- fmod(x, y)
- Floating point remainder of x divided by y.
- hypot(x,y)
- Hypotenuse calculator. If the projection of a straight line segment onto the X axis is x units long, and the projection of that line segment onto the Y axis is y units long, then the line segment is hypot(x,y) units long (assuming boring old Euclidean geometry.) Equivalent to sqrt(x*x+y*y).
- int(x)
- Convert number to integer by truncation.
- isqrt(x)
- Compute the integer part of the square root of x.
- log(x)
- Natural logarithm.
- log10(x)
- Logarithm with respect to base 10.
- max(x,...)
- Return the one argument with the greatest value
- min(x,...)
- Return the one argument with the least value
- pow(x,y)
- Power function. In FORTRAN notation, x**y.
- rand()
- Random number. Uses uniform distribution over the range [0,1). This RNG is not suitable for cryptography.
- round(x)
- Round to nearest whole number. Not suitable for financial rounding.
- sin(x)
- Sine (input in radians.)
- sinh(x)
- Hyperbolic sine.
- sqrt(x)
- Square root (well, the positive square root only. And Tcl doesn't do complex math, so the input had better be positive...)
- srand(x)
- Seeds the random number generator with the given value. Each interpreter has its own random number generator, which starts out seeded with the current time.
- tan(x)
- Tangent (input in radians.)
- tanh(x)
- Hyperbolic tangent.kjh
- wide(x)
- Take any numeric value, and return the low order 64 bits of the integer value of the argument
Mathematical Expressions edit
Simple addition:set a [expr {1 + 2}]mathematical functionsset a [expr {sqrt(4)}]martin Lemburg: The following returns 1 because [expr] " 2 " will be converted to 2:set a [expr {" 2 " == [string trim " 2 "]}]To ensure that expression evaluates to a floating point number, use an [expr] like double():set a 1
set b 2
expr {double($a)/$b}or, to get an integer:expr {entier($a/$b)}int() would also have worked, but entier() is more generalOrder of Precedence edit
The following returns returns 4, rather than -4 as some might expect:set a [expr {-2**2}]returns 1 because 2==2 is evaluated firstset a [expr {5&2==2}]String Operands edit
[expr] tries to interpret operands as numeric values, but it does not try to recognize complete numeric epressons in individual values, so a value "2*3" will be interpreted as a string:set y 2*3; puts [expr {$y}] ;# ==> 2*3
set y 2*3; puts [expr {$y+0}] ;# ==> can't use non-numeric string as operand of "+"Literal String Operands edit
[expr] implements a little language distinct from standard Tcl. One difference is that [expr] requires strings to be quoted:% if {joe eq mike} {puts wow}
syntax error in expression "joe eq mike": variable references require preceding $
% if {"joe" eq "mike"} {puts "wow"}
% if {{joe} eq {mike}} {puts {wow}}
%If [expr] syntax was the same as Tcl syntax, a Tcl bareword string would be accepted, but it is not.% puts wow wow % set a abc abc %If you prefer consistency, then always quote strings, but note that at some point [expr] may grow the feature of accepting bareword strings.
Canonical Number Form edit
If the value of an [expr] is numeric, it will transformed into a canonical numeric form:set val 0x10
puts $val ;# 0x10
set val [expr {$val}]
puts $val ;# 16puts [expr {[join {0 x 1 0} {}]}] ;# 16In other words, [expr] may mutate strings that can be interpreted as numbers, which is a potential gotcha for the programmer using string functions of [expr] while not considering that they may have a numeric interpretation.Floating-Point Arithmetic edit
[expr] uses floating point arithmetic, so strings representing decimal fractions that don't have a precise floating-point representation will be given to a close-enough floating-point representation. In the following example, "36.37" gets a floating-point representation that approaches 36.37:expr {int(36.37*100)}If that value is subsequently used as a string, it becomes necessary to somehow convert it. Over the years, the default string conversion has varied. For Tcl version 8.5.13, it looks like3636.9999999999995RS points out that version 8.4.9 provided the following results, and that that braced or not, [expr] returns the same (string rep of) double as well as integer, so the issue of bracing one's expressions is not relevant to the issue of floating-point to string conversion.
% expr 36.37*100
3637.0 ;#-- good enough...
% expr {36.37*100}
3637.0 ;#-- the same
% expr {int(36.37*100)}
3636 ;#-- Hmm
% expr int(36.37*100)
3636 ;#-- the same
% info pa
8.4.9One way to get "3637" would be to use round():expr {round(36.37*100)}The [format] command can also be useful, but the main point is to remain aware of the context and decide if and how to use floating-point operations.LV: My response on comp.lang.tcl was that I thought it was a shame that [expr] (or perhaps it is Tcl) didn't use the same mechanism for both calculations of 36.37 * 100 ; that way, the results would at least be consistent. Even if they were consistently wrong, one would be able to at least to live within the law of least surprise. As it is, until one experiments, one won't know which way that Tcl is going to round results.[EPSJ]: This may be a side effect of the IEEE floating point standard. This is done in hardware to guarantee the convergence in the case of a series of math algorithms. The rule is that the mantissa of a floating point number must be rounded to the nearest even number. As 36.37 cannot be represented exactly in float point it ends up being a small fraction below the intended number. On the other side 36.38 moves on the other direction. Look the following result:() 60 % expr int(36.380*100) 3638 () 61 % expr int(36.370*100) 3636x86 floating point hardware allows this to be configurable to nearest even, nearest odd, and a few more options. But usually nearest even is the default. The result may seem inconsistent, but it is intentional.
pow() vs ** edit
LES 2005-07-23:% expr pow(5,6) 15625.0 % expr 5**6 15625Two syntaxes, two slightly different results. Is that intentional?RS: Yes. While pow() always goes for double logarithms, ** tries to do integer exponentiation where possible.
Precision edit
davou: What is the precision of expr's functions, and how can it be expanded upon?Lars H: That's generally determined by the C library functions that implement them. It depends on where (and against what) Tcl is compiled. For "real" numbers that means doubles, which are floating-point numbers of typically about 17 decimal digits precision (but how many of these are correct varies between functions and platforms). For integers Tcl has traditionally used longs, which in most cases means 32-bit two's complement integers ($tcl_platform(wordSize) tells you the actual number of bytes), but as of Tcl 8.5 it supports (almost) arbitrarily large integers (googol magnitude is no problem anymore, whereas googolplex magnitude wouldn't fit in the computer memory anyway). As for extending what the core provides, tcllib provides math::bignum and math::bigfloat.Nan and Inf edit
At least as of Tcl 8.5, NaN and Inf are potential values returning from expr.Interactions with locale edit
[expr]'s parsing of decimals may be hampered by locale - you might get syntax error in expression 1.0Brace Your Expressions For Syntax edit
[expr] resolves variables in the context of its caller, and each variable value becomes exactly one operand in the expression. Consider the following:set color1 green
set color2 green
expr {$color1} eq {$color2} ;# 1But if the arguments are not bracketed, there is an error in the expression syntax:#wrong expr $color1 eq $color2
invalid bareword "green"
in expression "green eq green";
should be "$green" or "{green}" or "green(...)" or ...This is because in [expr] syntax, strings should be quoted or bracketedAnother example illustrating the same point:set a "abc"
set b [list 123 abcd xyz lmnop]
expr $a in $b
# invalid bareword "abc"
# in expression "abc in 123 abcd xyz lmnop";
# should be "$abc" or "{abc}" or "abc(...)" or ...
expr {$a in $b}
# 0
expr {$a ni $b}
# 1
% expr $a == "foo" ? true : false
invalid bareword "abc"
% expr {$a == "foo" ? true : false}
falseBrace Your Expressions for Performance edit
In addition, [expr] is much more performant when it has exactly one argument. The argument must either be brace-quoted or be a single variable substitution, since this allows byte-compilation.AMG: More precisely, the argument must not contain multiple substitutions or be the concatenation of substitutions and literal text. The goal is for there to be a persistent Tcl_Obj in which to store the compiled math expression. If [expr] has to concatenate its arguments (i.e. it is passed more than one argument), or if [Tcl] has to concatenate the results of multiple substitutions and literal substrings, then the math expression will be in a temporary Tcl_Obj which must be regenerated every time [expr] is called.Fast:expr {2 + 2} ; # Preferred
expr 2+2 ; # Valid but lazy (1)
expr "2 + 2" ; # Valid but not preferred (2)
expr 2\ +\ 2 ; # Valid but ugly (3)
expr $expression ; # Valid
expr [expression] ; # Valid(1) This style is easy to type and is fine for interactive use, but you will lose performance (and correctness and security) if you use this notation in combination with $variable and [script] substitutions.(2) Same problems as (1). Use braces instead.(3) Same problems as (1), plus you might forget a backslash before a space, thereby forcing [expr] to concatenate its arguments.Slow:expr 2 + 2 ; # Slow since [expr] must concatenate its arguments expr 2 + $x ; # Slow since [expr] must concatenate its arguments, also unsafe expr 2+$x ; # Slow since Tcl must concatenate to determine argument, also unsafe expr "2 + $x" ; # Slow since Tcl must concatenate to determine argument, also unsafe
Brace Your Expressions for Security edit
AMG: The security problems of unbraced expr expressions are very similar to SQL injection attacks. Notice how sqlite's Tcl binding does its own variable expansion to avoid this very problem. Many, many sh scripts have this problem as well because the default is to apply multiple passes of interpretation.Remember [if], [for], and [while] edit
AMG: The above speed and security concerns also apply to [if], [for], and [while] since they share the expression engine with [expr].Additionally, [for] and [while] really do need their expressions to be braced. In order for the loop to execute a nonzero but finite number of times, the expression's value must not be constant; but if they're not braced, their value is determined before the loop can begin.The exception is when the expression (as opposed to value) is contained in a variable, in which case it must not be brace-quoted, or else the command would try to treat the expression as a (string) value and almost certainly fail to convert it to a boolean value.Consider what would happen if this script were actually working with user input:
#DON'T EXECUTE THIS SCRIPT!!!
set x {[exec format C:\\]}
set j {[puts Sucker!]}
#C:\ get formatted in the next command
set k [expr $x / $j.]On the other hand,set k [expr { $x / double($j) }]gives a much more reasonable result:argument to math function didn't have numeric value
while executing
"expr { $x / double($y) }"
invoked from within
"set k [expr { $x / double($y) }]
"
(file "foo.tcl" line 3)
The "Dot" Trick for Unbraced Expressions edit
Unless you know exactly what you are doing, unbraced expressions are not recommended. Nevertheles...With unbraced expressions, a "." can be appended to a variable to get [expr] to interpret the value as a float, but the double() function is a better alternative:set x 1; set j 2
# works (but don't do this)
expr $x/$j.
#an accepted way to do it
expr {double($x)/$j}
# error: syntax error in expression "$x/$j." (expr parser)
expr {$x/$j.}It's faster, too:set script1 {
set x 1
set j 2
set k [expr $x / $j.]
}
set script2 {
set x 1
set j 2
set k [expr { $x / double($j) }]
}
foreach v { script1 script2 } {
puts "$v: [time [set $v] 10000]"
}
#script1: 38 microseconds per iteration
#script2: 9 microseconds per iteration
#[pyk] 2012-11-28: what a difference a few years makes (an "old" 3.06Ghz Intel Core 2 Duo):
#script1: 4.4767364 microseconds per iteration
#script2: 0.7374299 microseconds per iterationRS: This was just to demonstrate the differences between the regular Tcl parser and expr's parser, not recommended practice. Another example is substitution of operators:
set op "+"
expr 4 $op 5
9
expr {4 $op 5}
syntax error in expression "4 $op 5"See the for page on a case where that helped.History edit
On 1992-12-28 JO published the voting results 37 : 8 in favor of embedded functions() vs. separate [commands] - [1]Dustbin edit
(Outdated) Expr GotchasAddition% expr (1<<31)-1 2147483647 % expr 2147483647 + 2147483647 -2Multiplication
% expr sqrt((1<<31)-1) 46340.9500011 expr 46341*46341 -2147479015These are results of Tcl 8.4 and older versions using a 32-bit representation for integers. Check out TIP #237
, an implemented TIP describing arbitrary-precision Integers for Tcl. This is available in Tcl 8.5.See Also edit
- A little math language
- adds features & sugar to expr
- A real problem
- Additional math functions
- Arbitrary precision math procedures
- Brace your expr-essions
- compute
- more sugar for expr
- Converting numbers from arbitrary bases
- DebuggingExprCalls
- rwm sometimes it is difficult to debug expr calls where the operands are variables. DebuggingExprCalls explains how to wrap expr to help with these cases.
- double substitution
- expr problems with int
- limits of number representation (both integer and float) inherited from C
- for
- How can I do math in Tcl
- if
- Importing expr functions
- use expr's functions without explicitly calling that, see Importing expr functions.
- Math function help
- Modeling COND with expr
- Braced expressions can span several lines
- Numerical Analysis in Tcl
- Sample Math Programs
- extremely simple math examples
- Tcl help
- TIP #123

- Adding an Exponentiation Operator to the expr Command
- TIP #174

- Math Operators as Commands
- TIP #182

- Add 'expr bool' Math Function
- TIP #201

- Add 'in' Operator to expr
- TIP #201

- Creating New Math Functions for the 'expr' Command (tcl::mathfunc)
- TIP #237

- Arbitrary-Precision Integers for Tcl
- while
Half-Bakery edit
RS suggests expr's arguments could be reparsed so that full mathematical expressions in variable values would interpreted as suchRS 2003-04-24: Here's a tiny wrapper for friends of infix assignment:proc let {var = args} {
uplevel 1 set $var \[expr $args\]
} ;#RS% let i = 1
1
% let j = $i + 1
2
% let k = {$i + $j}
3set y 2*3; puts [expr $y+0] ;# ==> 6AM: The problem with variables whose values are actually expressions is that they change the whole expression in which they are used. The performance gain for caching the parsed expression will then be lost.
Discussion edit
[Wookie]: I had some trouble recently using expr to calculate time offsets. I had 2 time stamps in the form hh:mmSo I had 4 variables h1, m1, h2, m2 and one of my expr functions wasset result [expr {$m1 + $m2}]As many of you may be thinking, you fool! what about 08 and 09, which will get treated as invalid octal. So after some grumbling I thought okay so I have to trimleft them. Bit verbose but who cares:set m1 [string trimleft $m1 0] set m2 [string trimleft $m2 0] set result [expr ($m1 + $m2)]Now what could possibly go wrong with that... well obviously 00 becomes the empty string, which causes unexpected closed parameter in the expr. So now I have to check for the empty string. So...
set m1 [string trimleft $m1 0]
if {$m1=={}} {set m1 0}
set m2 [string trimleft $m2 0]
if {$m2=={}} {set m2 0}
set result [expr {$m1 + $m2}]... and then repeat it for the hours. It all seemed very clumsy. So I came up with this, which may solve many of the conversion issues in this section.scan "$h1:$m1 $h2:$m2" "%d:%d %d:%d" h1 m1 h2 m2
set result [expr {$m1 + $m2}]All the conversions to int have been done and leading 0's have been stripped and returns 0 if the value is all 0s. This works for float and probably double (though I've not tried). Can anyone see any problems with this approach?glennj: No, scan is definitely the way to parse numbers out of dates and times. However, for date arithmetic, nothing beats clock.# adding a delta to a time set h1 12; set m1 45 set h2 3; set m2 30 clock format [clock add [clock scan "$h1:$m1" -format "%H:%M"] $h2 hours $m2 minutes] -format %T ;# ==> 16:15:00What are you trying to do with your two times?

