Tclの数式について

Tclのインタプリタは数式を評価する機能がありません。その代わりexprコマンドが数式の評価を行います。

exprコマンドは算術演算子(+, -, *, / など)の他に、論理演算子(AND, OR, NOTなど)やビット演算子なども使えます。数学関数(sin, powなど)もサポートされています。

exprコマンドの書式

[書式]

expr arg ?arg arg … ?

arg: 数値や変数、演算子(+, -, *, / など)

exprコマンドはargを連結して式として評価し、結果を数値として返します。

例えば、 expr 3.1 + 2 は 5.1 を返します。

メモ

argは「argument」の略。
argumentを一般の辞典で引くと日本語では議論、口論、論点、主張などの意味で訳さています。しかし、コンピューター用語の辞典では、「引数」という意味で訳されています。

簡単な計算

四則演算

四則演算の演算子を使用した計算のやり方は以下のようになります。

[使用例]

% expr 3 + 5
8

四則演算の演算子は以下の種類があります。

演算子 意味
+ 加算(足し算)
減算(引き算)
* 乗算(掛け算)
/ 除算(割り算)

浮動小数点数の扱いについて

浮動小数点数が導入されるまでは整数が使われます。

[使用例]

% expr 7 / 2        ----(1)
3
% expr 7.0 / 2      ----(2)
3.5
% expr 8.0 / 2.0    ----(3)
4.0

(1)

7 / 2 は、3.5ではなく3が返されます。

(2)

7.0 / 2 のように、小数点数を使用すると、3.5が返されます。

(3)

4ではなく4.0が返されます。

四則演算以外の算術演算子

算術演算子には、四則演算のほかに、剰余(余り)、べき乗が使えます。

[使用例]

% expr 5 % 3   ---(1)
2
% expr 5 ** 3  ---(2)
125

(1)剰余演算子(余り)

「%」は余りを返します。5を3で割ると1余り2。

(3)べき乗演算子

「**」はべき乗の計算をします。5x5x5=125

式を「{}」で囲む

exprコマンドのマニュアルを確認すると以下の内容が記述されています。

PERFORMANCE CONSIDERATIONS

Enclose expressions in braces for the best speed and the smallest storage requirements. This allows the Tcl bytecode compiler to generate the best code.

As mentioned above, expressions are substituted twice: once by the Tcl parser and once by the expr command. For example, the commands

[翻訳すると]

パフォーマンスの考察

最高の速度と最小のストレージ要件のために、式を中括弧で囲みます。 これにより、Tclバイトコードコンパイラは最適なコードを生成できます。

上記のように、式は2回置換されます。1回はTclパーサーによって、もう1回はexprコマンドによって置換されます。

exprコマンドに渡す式は波括弧で囲んだ方がパーフォーマンスがいいようです。

例1.

% set x 2
2
% expr {2 + 2}   ---(1) # 早い
4
% expr 2+2       ---(2) # 早い
4
% expr "2 + 2"   ---(3) # 早い
4
% expr 2 + 2     ---(4) 
4
% expr 2 + $x    ---(5-1) # 遅い
4
% expr 2+$x      ---(5-2) # 遅い
4
% expr "2 + $x"  ---(5-3) # 遅い
4

[説明]

上の例は(1)が最も早く、(5)が一番遅くなります。

これはどういうことかと言うと、exprコマンドは次のような動作をするようです。

(1)のように値が連結されていない1つの引数がexprコマンドに渡されると、引数をそのままバイトコードにコンパイルすることができます。これが最も効率的に処理されます。

(4)のように値が連結されていない複数の引数がexprコマンドに渡されると、exprコマンドは引数を連結する処理を行うのでパフォーマンスが低下します。

もし、波括弧で囲むことができない場合、(2)のように値と演算子を連結した表記方法が有効です。

exprコマンドがその引数を連結しなければならない場合、または(5)のようにTclが複数の置換と数値や演算子などの部分を連結する必要がある場合は、数式は一時Tcl_Objに格納され、exprコマンドが呼び出されるたびに再生成されます。

例2

% set x 2
2
% set y 2*2
2*2

% expr {2 + $x}
4
% expr {2 + $y}   ---(1)
can not use non-numeric string as operand of "+"
% expr 2 + $y     ---(2)
6

[説明]

(1)

波括弧で囲む場合、変数置換の結果に数値以外の文字が含まれていると、文字列と認識されてしまい、波括弧による表記は機能しません。

(2)

式:2+2*2 が実行されます。

[参考]

expr
Tclers wiki
Brace your expr-essions
Tclers wiki

浮動小数点値の有効桁数と表現について

浮動小数点値の有効桁数と表現はTcl8.4までとTcl8.5以降で、違いがあります。

Tcl8.4までの挙動

[使用例]

% set tcl_precision   ---(1)
12
% expr 5 / 3.0
1.66666666667
% set tcl_precision 17
17
% expr 5 / 3.0
1.6666666666666667

% expr 0.2            ---(2)
0.20000000000000001
% expr 0.5
0.5
% expr 0.25
0.25

[説明]
(1)桁数について

有効桁数については変数tcl_precisionに必要な有効桁数を設定することで変更できます。デフォルトで12桁の有効数字をもつ文字列として整形されます。最大値は17桁まで設定できます。
IEEEの倍精度浮動小数点数(64ビットの浮動小数点数)を表現するには、17桁の演算精度があれば、情報が欠落せずに表現できます。

(2)小数点数の表示について

浮動小数点数もコンピューター内部では2進数(0と1)で取り扱っている為、正確に表現できずに誤差が生じます。変数tcl_precisionで最大17桁まで設定できますが、17桁にすると丸め処理が行われないので、数値を文字列に変換する際に、2進数の正確な値に、より近い数値で表現されます。

Tcl8.5以降の挙動

[使用例]

% set tcl_precision   ----(1)
0
% expr 5/3.0
1.6666666666666667

% expr 0.2            ----(2)
0.2
% expr 1.4
1.4

% expr 3*1.4          ----(3)
4.199999999999999

% set tcl_precision 12
12
% expr 3*1.4
4.2

[説明]
(1)桁数について

Tcl8.5以降は、デフォルトで17桁の有効数字をもつ文字列として整形されますが、変数tcl_precisionは 17 ではなく0 になっています。

(2)tcl_precisionが0の場合

例えば、数値:0.2は0.20000000000000001が2進数の正確な値により近い数値だとしても0.2として表示します。

(3)計算結果の表現

計算結果は2進数の正確な値に、より近い値を表示します。expr 3*1.4 は4.2ではなく4.199999999999999と表示します。
tcl_precision 12 にすると以前(Tcl8.4まで)と同じ表現方法になります。

メモ

有効桁数はTclのシステム変数「tcl_precision」で変更可能ですが、変更はレガシー・コードとの互換性に対してのみ使用し、それ以外はデフォルトのまま変更しないことが推奨されています。もし、浮動小数点値の表示精度を制御する必要がある場合は、formatコマンドを使用することが推奨されています。

[参考]

tcl_precision
Tclers wiki

formatコマンドで整形する

[使用例]

% set x [expr 3*1.4]
4.199999999999999

% format %.12g $x
4.2

formatコマンドの %.12g は12桁の浮動小数点数に変換します。

formatコマンドの使い方については、以下の記事で紹介しています。

Tcl - 文字列を整形(書式化)する -format-
この記事は、変換指定子の書式の各項目(フラグ、最小フィールド(幅)、精度、サイズ修飾子、変換文字)に指定できる値と意味、formatコマンドの使い方を、いくつか例を使ってを紹介しています。

任意精度の整数計算

Tcl8.5以降、任意精度で整数計算ができます。

[使用例]

% set x 9999999999999999999999999999999999999999; #40桁
9999999999999999999999999999999999999999
% expr $x + 3
10000000000000000000000000000000000000002

この記事以外のexprコマンドの使い方は、必要に応じて以下の記事を参考にしてください。

コメント

タイトルとURLをコピーしました