Version 155 of expr

Updated 2013-03-25 14:46:54 by pooryorick

Summary

expr - Evaluate an expression

Synopsis

expr arg ?arg arg ...?

officieal reference
man page, 8.4
mathfunc man page
mathop man page
tcl_precision

expr concatentates its arguments, evaluates this result as a Tcl [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 implements a little language that has a syntax separate from Tcl. [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: A value recognized as boolean by [string is boolean... can be used directly,

  • true, on, yes
  • false, off, no

Functions take the form,

Any of these values may be abbreviated, and upper-case spellings are also acceptable. See the Tcl_GetBoolean man page

name(argument?)

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.

name(argument,argument ...)`

Refer to the Operands section of the expr man page for the syntax rules.

`[[[expr]]` [concat]enates 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}
expr {$val1} + ${val2}

evaluates to 14.2.

This is an equivalent way of writing the previous ﷒[brace or otherwise expr {$val1+$val2}

This allows `expr` to do the interpretation, rather than having Tcl interpret
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.
`expr` expressions differ from [C] expressions in the way that operands are
[Tcl] expressions differ from C expressions in the way that operands are
(comparison) and lists (membership).




Since Tcl 8.5, many operators have command-equivalents in the
In spite of the name '''mathop''', some of the operators are string-oriented, rather
Note that many operators have command-equivalents in the [namespace]
'''::[tcl::mathop]''' from Tcl 8.5 onwards.
The following is a chart of operators, in order of precedence (tightest-binding
[[The term '''mathop''' is a misnomer, since some of the operators included in this namespace are string, rather than math, oriented...]]
&| [-] [+] [~] [!] | 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). |&
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.) |&
&| [+] [-] | 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 `expr`' operator `==` considers them to be equivalent numbers.|&
&| [<] [>] [<=] [>=] | 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 exclusive OR.  A bit is set in the result when the corresponding bit is set in ''precisely one'' of the arguments. |&
&| [<<pipe>>] | 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 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 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. |&
&| [<<pipe>><<pipe>>] | 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. |&



See the [http://www.tcl.tk/man/tcl/TclCmd/mathfunc.htm%|%mathfunc man page].
See the mathfunc man page, listed above, for the Tcl 8.5 man page information
on `[[[expr]]` builtin functions.
The following is a list of builtin functions:
   '''[abs]'''(x):   Absolute value (negate if negative).
*** builtin ***
   '''[acos]'''(x):   Inverse cosine (result in radians).
   '''[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

   '''[cos]'''(x):   Cosine (input in radians.)
   '''[cosh]'''(x):   Hyperbolic cosine.

   '''[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.


   '''[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.


   '''[sin]'''(x):   Sine (input in radians.)

   '''[sqrt]'''(x):   Square root (well, the positive square root only.  And Tcl doesn't do complex math, so the input had better be positive...)






** Mathematical Expressions **


Simple addition:

set a expr {1 + 2}

mathematical functions

set a expr {sqrt(4)}

[martin Lemburg]: The following returns `1` because `" 2 "` will be interpreted
[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 `double()`
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 general


** Order of Precedence **

The following returns returns 4, rather than -4 as some might expect:

set a expr {-2**2}

The following returns `1` because `2==2` is evaluated first:
returns 1 because 2==2 is evaluated first
set a [expr {5&2==2}]

AMG: The order of bitwise operations (|, &, and ^) may seem totally bogus, but it's inherited from C, which in turn inherited it from an early prototype version of C which lacked separate logical operators (&& and ||) [L1 ]. I wouldn't cry if a new language (not Tcl) decided to break compatibility with C in this respect.

String Operands

[[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; expr {$y}   ;# ==> 2*3
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 "+"

To pass a complete expression stored in a variable, omit the braces so that Tcl

expr implements a little language distinct from the language described in the rules of Tcl. One [[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 {{joe} eq {mike}} {puts {wow}}
%

To insert a literal value when templating an expression, use an [identity
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.



If the return value of `expr` is numeric, it is transformed into a canonical
If the value of an `[[[expr]]` is numeric, it will transformed into a canonical

set val 0x10 puts $val ;# 0x10 set val expr {$val} puts $val ;# 16

puts expr {[join {0 x 1 0} {}}] ;# 16


In other words, `expr` may mutate strings that can be interpreted as
In 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




`expr` uses floating point arithmetic, so strings representing decimal
`[[[expr]]` uses floating point arithmetic, so strings representing decimal
to a close-enough representation.  In the following example, `36.37` gets a
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 like

3636.9999999999995

[RS] 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
that braced or not, `[[[expr]]` returns the same (string rep of) double as well
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.9

One way to get `3637` would be to use `round()`:
One way to get "3637" would be to use `round()`:

expr {round(36.37*100)}

`[format]` can also be useful, but the main point is to remain
The `[[[format]]` command can also be useful, but the main point is to remain

[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
that `[[[expr]]` (or perhaps it is Tcl) didn't use the same mechanism for
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) 3636

x86 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 **
** pow() vs ** **
[LES] 2005-07-23:

% expr pow(5,6) 15625.0

% expr 5**6 15625

Two 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 **

[davou]: What is the precision of functions in `expr`, and how can it be
[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
implement them. It depends on where (and against what) Tcl is compiled.
For "real" numbers that means '''double'''s, 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 '''long'''s, 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] **


At least as of Tcl 8.5, [NaN] and [Inf] are potential values returning from
`expr`.
expr.
[Philip Smolen] I've never seen expr return NaN.  I wish it would!

Interactions with locale

Interactions with locale

[expr]'s parsing of decimals may be hampered by [locale - you might get

expr concatenates its arguments into an expression. Consider the following [[expr] resolves variables in the context of its caller, and each variable value becomes exactly one operand in the expression. Consider the following:

expr 5 > {} ;# -> missing operand at _@_
set color2 green

expr {$color1} eq {$color2} ;# 1

Concatenated, the arguments form the script, `green eq green`, in which the two
But if the arguments are not bracketed, there is an error in the expression
syntax:
Another example illustrating the same point:

#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 bracketed

set a "abc"
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 in $b}
# 0
expr {$a ni $b} ;#-> 1
expr {$a ni $b}
# 1

% expr $a == "foo" ? true : false % expr {$a eq "foo" ? true : false} % expr {$a == "foo" ? true : false}




When exactly one unconcatenated value is passed to `expr`, the argument can be

In addition, `[[[expr]]` is usually much more performant when its non-literal
arguments are braced, since this allows byte-compilation.
'''Fast:'''

AMG: The security problems of unbraced expressions are very similar to

AMG: The security problems of unbraced expr expressions are very similar to SQL injection attacks. Notice how sqlite's Tcl binding does its own this problem as well because the default is to apply multiple passes of interpretation.

See also double substitution.

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

Unless you know exactly what you are doing, unbraced expressions are not recommended. Nevertheles...

With unbraced expressions, . (\x2e) can be appended to a variable to get expr 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} {
foreach v { script1 script2 } {
}

#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 iteration

RS: This was just to demonstrate the differences between the regular Tcl parser and the parser for expr', not recommended practice. Another example is parser and expr's parser, not recommended practice. Another example is

set op +
set op "+"
9
expr {4 $op 5}
syntax error in expression "4 $op 5"

See the for page on a case where that helped. See the for page on a case where that helped.

Bytecode compilation and performance

In Embedded vs. separate commands , 1992-12-38, JO published the voting results 37:8 in favor of embedded functions() vs. separate [commands] On 1992-12-28 JO published the voting results 37 : 8 in favor of embedded functions() vs. separate [commands] - [L2 ]

(Tcl 8.4 and older) 32-bit integer limitations

Dustbin

Addition (Outdated) Expr Gotchas

% expr (1<<31)-1
2147483647

% expr 2147483647 + 2147483647
-2

Multiplication

% expr sqrt((1<<31)-1)
46340.9500011

expr 46341*46341
-2147479015

These are results of Tcl 8.4 and older versions using a 32-bit representation for integers. for integers. Check out TIP #237 , an implemented TIP describing arbitrary-precision Integers for Tcl. This is available in Tcl 8.5. Tcl 8.5 features abritrary-precision integers. See

See Also

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 [L3 ]
Adding an Exponentiation Operator to the expr Command
TIP #174 [L4 ]
Math Operators as Commands
TIP #182 [L5 ]
Add 'expr bool' Math Function
TIP #201 [L6 ]
Add 'in' Operator to expr
TIP #232 [L7 ]
Creating New Math Functions for the 'expr' Command (tcl::mathfunc)
TIP #237 [L8 ]
Arbitrary-Precision Integers for Tcl
while

Half-Bakery

RS suggests expr's arguments could be reparsed so that full mathematical

RS 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}
3
set y 2*3; puts [expr $y+0] ;# ==> 6

AM: 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.

AMG: This reopens the door to all the security, performance, and correctness problems solved by bracing one's expressions.

Discussion

Wookie: I had some trouble recently using expr to calculate time Wookie: I had some trouble recently using expr to calculate time offsets. I had 2 time stamps in the form hh:mm So I had 4 variables h1, m1, h2, m2 and one of my expr functions was So I had 4 variables h1, m1, h2, m2 and one of my expr functions was

set 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 expression. 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 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:00

What are you trying to do with your two times?