expr

ReferenceTOPKeywords

コマンド名

expr - 式を評価します。

構文

expr arg ?arg arg ... ?

解説

arg を(スペースを挟んで)連結し 、Tclの式として評価した結果値を返します。Tcl式において使用可能な演算子はC言語の式において許される演算子のサブセットであり、それらは対応するC言語の演算子と同じ意味と優先順位を持っています。 式は常に数値の結果(整数または浮動小数値) を持ちます。例えば、式
expr 8.2 + 6
を評価すると 14.2 になります。
Tclの式がC言語の式と異なる点はオペランドの指定の方法にあります。また、Tclの式は数でないオペランドや文字列の比較をサポートしています。

OPERANDS

Tclの式はオペランドと演算子と括弧により構成されます。
空白は、オペランド,演算子,括弧の間に使うことができますが、実行時に無視されます。
オペランドはできうる限り整数値として解釈されます。
整数値は10進(普通の場合),8進 (オペランドの最初の文字が0である場合),16進(オペランドの最初2文字が0xである場合)で指定できます。
オペランドが前述の整数フォーマットでない場合は、可能であれば浮動小数点数として扱われます。
浮動小数点数は、ANSI‐準拠のCコンパイラ(f, F,l,Lという接尾辞が殆ど使用できないということを除けば)が認めるフォーマットが全て使用できます。
例えば、以下は有効な浮動小数点数です。
2.1、3.、6e4、7.91e+16。
数値として解釈ができない場合、オペランドは文字列としてみなされます(その場合は使用できる演算子は限定されます)。

32ビットシステム上では、整数MAX_INT(0x7FFFFFFF)とMIN_INT(-0x80000000)は32ビット値として表示され、その範囲以外の整数値は(可能であれば)64ビット値として表示されます。

オペランドは次の方法の何れかで指定することができます。

[1]整数か浮動小数点のいずれかの数値とした場合。
[2]標準の$表記法を使って、Tcl変数とした場合、変数の値はオペランドとして使われます。
[3]二重引用符で囲まれた文字列とした場合。式を分析する際、引用符の間にある情報に対して、バックスラッシュ,変数,コマンドの置換を行い、その結果値をオペランドとして使います。
[4]中括弧"{ }"で囲まれた文字列とした場合。左中括弧とマッチした右中括弧の間の文字は、置換なしでそのままオペランドとして使われます。
[5]大括弧"[ ]"で囲まれたTclコマンドとした場合。そのコマンドが実行した結果はオペランドとして使われます。
[6]数学関数とした場合。引数には前述のフォーマットのオペランドも使用できます。(例えばsin ( $x ))。定義された関数のリストは下記を参照してください。

前述の、式の中に含まれている変数の置換やコマンド置換は、exprコマンドに備わっている機能です。 しかし、式がexprコマンドに渡される前に、その式がコマンド解析によって先に置換されることに注意してください。
コマンド解析によって式が置換されてしまうのを防止したい場合には、下記の例の様に式を中括弧で囲みます

下記は簡単な式の例です。
変数aの値が3、変数bの値が6であるとき、各行の左にある式を評価すると右の値になります。

expr 3.1 + $a                  6.1
expr 2 + "$a.$b"                5.6
expr 4*[llength "6 2"]            8
expr {{word one} < "word $a"}      0

 

演算子

有効な演算子は下記のとおりです。
優先度の高い順にグループ化しています。

- +~ !
* / %
+ -
<< >>
< > <=>=
== !=
eq ne
&
^
|
&&
||
x ?y : z
- +~!
単項演算子のマイナス・プラス・ビット演算子のNOT・論理演算子のNOT。
これらはいずれも文字列に適用できません。
また、ビット演算子のNOTは整数のみに適用されます。
* / %
乗算・除算・剰余。
これらはいずれも文字列に適用されません。
また、剰余は整数のみに適用されます。
剰余は常に除数と同じ符号を持ち、その絶対値は除数より小さくなります。
+ -
加算・減算。
数値であればどのオペランドにも適用できます。
<< >>
左シフト・右シフト。
整数のみに有効です。
右シフトは常に符号を保有します。
< > <= >= 
比較演算子の小なり・大なり・以下・以上。
真であれば1を、そうでなければ0を返します。
これらの演算子は数値だけでなく文字列にも適用できますが、その場合は文字列比較となります。
== !=
比較演算子のイコール・非イコール。
それぞれ10を返します。
全てのオペランドに有効です。
eq ne
比較演算子の文字列イコール・文字列非イコール。
それぞれ10を返します。
文字列のみに有効です。
&
ビット演算子のAND。
整数のみに有効です。
^
ビット演算子の排他的論理和(XOR)。
整数のみに有効です。
|
ビット演算子のOR。
整数のみに有効です。
&&
論理演算子のAND。
オペランドが両方とも0でなければ1を、そうでなければ0を返します。数値のオペランド(整数また浮動小数点数)のみに有効です。
||
論理演算子のOR。
オペランドが両方とも0であれば1を、そうでなければ0を返します。
数値のオペランド(整数また浮動小数点数)のみに有効です。
x?y:z
C言語ライクなIf-then-else。
xを評価した値が0でなければ、結果はyの値に、そうでなければzの値になります。
xは数値でなければなりません。

各演算子についての詳解は、C言語マニュアルを参照してください。
同じ優先順位を持つ2項演算子の評価は「左から右」の順になります。
例えば

expr 4*2 < 7

は0を返します。

&& ||   ?: 演算子は、C言語と同様に「遅延評価」を行います。
即ち結果を決定するのに必要とされないオペランドは評価されません。
例えば

expr {$v ? [a] : [b]}

において、$vの値に応じて、[a]または[b]のどちらか一方しか実際には評価されません。
注意すべきは、「遅延評価」が適用されるのは、全体の式が中括弧に括られている場合だけです。
そうでない場合は、exprコマンドを呼び出す前に、Tcl分析は[a][b]の両方を評価します。

 

数学関数

Tclは式において次の数学関数をサポートします。

abs (arg )
acos (rg )
asin (arg )
atan (arg )
atan2 (y, x )
ceil (arg )
cos (arg )
cosh (arg )
double (arg )
exp (arg )
floor (arg )
fmod (x, y )
hypot (x, y )
int (arg )
log (arg )
log10 (arg )
pow (x, y )
rand ( )
round (arg )
sin (arg )
sinh (arg )
sqrt (arg )
srand (arg )
tan (arg )
tanh (arg )
wide (arg )
abs (arg )
argの絶対値を返します。
Argは整数か浮動小数点のいずれかであり、その結果は同じフォーマットで返されます。

acos (arg )
範囲[0, pi]のラジアンにおけるargのアークコサイン(アーク余弦)を返します。
Argは範囲[ -11 ]にあります

asin (arg )
範囲[-pi/2pi/2 ]のラジアンにおけるargのアークサイン(アーク正弦)を返します。
Argは範囲[ -11 ]にあります

atan (arg )
範囲[-pi/2pi/2 ]のラジアンにおけるargのアークタンジェントを返します。

atan2 (y、x )
範囲[ -pipi]のラジアンにおけるy/x のアークタンジェントを返します。
xy は両方共に0でないもの。
x 0 を超えているならば、これはatan (y/x ) に相当します。

ceil (arg )
浮動小数点値argより大きく、最小の整数値(即ち、ゼロを小数部分にする) を返します。

cos (arg )
ラジアンで表現されたargのコサイン(余弦)を返します。

cosh (arg )
arg の双曲余弦(コサイン)を返します。
その結果がオーバフローを引き起こした場合、エラーが返されます。

double (arg )
argが浮動小数点値である場合、argを返し、そうでない場合、argを浮動小数点値に変換し、変換された値を返します。

exp (arg )
argの指数のものを返し、 e ** arg と定義されます。
その結果がオーバフローを引き起こした場合、エラーが返されます。

floor (arg )
浮動小数点値argより小さく、最大の整数値(即ち、ゼロを小数部分にする) を返します。

fmod (x, y )
x y によって割り、剰余を浮動小数点で返します。
y が0である場合、エラーが返されます。

hypot (x, y )
直角三角形の斜辺の長さsqrt ( x * x + y * y ) を算出します。

int (arg )
arg が整数値である場合はargを返します。
そうでない場合は arg をきりつめることで整数 (マシンのWordと同じサイズ、即ち32ビットシステム上の32ビット及び64ビットシステム上の64ビット) に変換し、変換された値を返します。

log (arg )
arg の自然対数を返します。
Argは正値でなければなりません。

log10 (arg )
arg の常用対数を返します。
Argは正値でなければなりません。

pow (x, y )
x y 乗値を計算します。
x が負である場合、y は整数値でなければなりません。

rand ( )
ゼロから1未満の、数学用語で言うと、範囲[0, 1 )の、浮動小数点数を返します。
シードはマシンの内部時計か、srand関数により設定します。

round (arg )
argが整数値である場合はargを返します。
そうでない場合はargを丸めることで整数に変換された値を返します。

sin (arg )
ラジアンで表現されたargのサイン(正弦)を返します。

sinh (arg )
arg のの双曲正弦(サイン)を返します。
その結果がオーバフローを引き起こした場合、エラーが返されます。

sqrt (arg )
arg の平方根を返します。
Arg は非負でなければなりません。

srand (arg )
乱数発生器のシードをリセットするために使われ、argは整数でなければなりません。
そのシードの最初の乱数を返します。
各インタプリタは自分自身のシードを持っています。

tan (arg )
ラジアンで表現されたarg のタンジェントを返します。

tanh (arg )
arg の双曲タンジェントを返します。

wide (arg )
arg を幅少なくとも64ビットの値に ( arg が32ビット数値であるならば、符号拡張によって)変換します。

これらの定義済み関数に加えて、 アプリケーションは Tcl_CreateMathFunc()を使って追加的な関数を定義することができます。

 

型,オーバフロー,精度

すべての整数に関わる内部的な計算はC言語のlong型で行われ、すべての浮動小数点数に関わる内部的な計算はC言語のdouble型で行われます。
文字列から浮動小数点数への変換は、指数オーバーフローが検出され、結果としてTclエラーが返されます。
文字列から整数への変換では、オーバーフローの検出はローカルCライブラリのいくつかのルーチンに依存します。
このため、結果は信用できないと見た方がいいでしょう。
どの場合でも、整数のオーバーフローとアンダーフローは一般的に中間結果として検出される確信はありません。
浮動小数点数オーバーフローとアンダーフローはハードウェアでサポートされている範囲で検出されます。
これは信頼できると考えられます。

整数、浮動小数点数、そして文字列オペランドの内部表現の間の変換は必要な場合、自動的に行われます。
算術演算では、浮動小数点数が導入されるまでは整数が使われます。
導入された後では浮動小数点数が使われます。
例えば

expr 5 / 4

は1を返します。
 そして、

expr 5 / 4.0
expr 5 / ( [string length "abcd"] + 0.0 )

は、両方とも1.25を返します。
浮動小数点数値は常に"."か"e"付きで返されます。
これは整数値のように見えるのを防ぐためです。
例えば

expr 20.0/5.0

4ではなく4.0を返します。

文字列演算

文字列値は比較演算子のオペランドとして使用できます。
しかし、e及びne演算子を除いて、式の評価ルーチンは可能であれば整数あるいは浮動小数点数として比較を行おうと試みます。
比較の演算数の1つが文字列で他が数値であれば、数値はC言語のsprintfの%d(整数の場合),%g(浮動小数点数の場合)により文字列に変換されてから比較されます。
例えば、

expr {"0x03" > "2"}
expr {"0y" < "0x12"}

は、両方とも1を返します。
最初の比較は整数比較を用いて行われます。
そして2番目は2つ目のオペランドを文字列18に変換した後で、文字列比較を用いて行われます。
可能な限り値を数値として扱うのは、Tclの傾向ですので、本当に文字列比較を行いたい場合は、値が任意であるときに"=="のような演算子を使うよりも、neまたはeqのような演算子、或いは stringコマンドを使った方が良いでしょう。

パフォーマンス考察

最高のスピードと最低の格納領域を実現するため、中括弧で式を囲みます。
これはTclバイトコードコンパイラに最適のコードを生成できます。
 

前述のように、式は2回、置換されます。
Tcl分析パーサによって1度、exprコマンドによって1度です。
例えば、コマンド

set a 3
set b {$a + 2}
expr $b*4

は、4の倍数ではなく11を返します。
これはTclの分析パーサが最初に変数 b を $a + 2に置換するためです。
そしてexprコマンドが式$a + 2*4を評価します。

ほとんどの式は置換の2回目をしてほしくありません。
それらの変数やコマンド置換は、中括弧で括られているかどうかに係わらず、これ以上置換を要求しない数値か文字列を作り出します。
しかしながら、いくつかの中括弧で括られていない式は置換の2ラウンドを必要とし、バイトコードコンパイラはこの状況を処理するための追加的な命令を発行しなければなりません。
コマンド置換を含み中括弧で括られていない式では、もっとも処理のコストが高いコードが要求されます。
このような式は式が実行されるたびに新しいコードを生成することで実装されなければなりません。

参照

array, string, Tcl

キーワード

arithmetic, boolean, compare, expression, fuzzy comparison


Copyright © 1993 The Regents of the University of California. Copyright © 1994-2000 Sun Microsystems, Inc. Copyright © 1995-1997 Roger E. Critchlow Jr.