Top > マニュアル > 文法 > 4.演算
  トップページへ   [ 一覧 | 検索 | 最終更新 ]   [ 差分 | バックアップ | 凍結 ]

演算

基本

C言語と同様の書式で四則演算、比較演算、代入、その他が可能です。
演算の順序は演算子毎に重み付けされた演算優先度に基づいて決定されます。また、ブラケット( )で囲まれた部分は最優先で演算されます。 演算子の種類と演算優先度は以下の通りです。

演算子                      意味          優先度

( ) [ ]                     ブラケット       高い
!                         否定
++ --                      1を足す/1を引く
* / %                      乗除算、剰余
+ -                       加減算
&                         フィードバック
== != >= <= > < _in_ !_in_         比較
&&                        論理積
||                        論理和
= :=                       代入
+= -= *= /= %= +:= -:= *:= /:= %:= ,=  演算して代入
,                            汎用配列要素の列挙   低い

コロン(":")付きの代入演算子は過去互換性を保持するために残されているもので、機能的にはコロン無しのものと同等です。

*は単項演算子です。

ブラケット( )については次項で詳説します。
カンマ演算子(",")、およびスクウェアブラケット[ ]については配列の項で詳説しています。
フィードバック演算子&については別項で詳説しています。 _in_と!_in_は文字列の包含チェックに使用する演算子です。

foo
{
    "or" _in_ "World"
}

_in_は左辺の文字列が右辺の文字列に含まれていれば1、含まれていなければ0を返します。!_in_はその逆です。
上の関数fooは1を返します。

比較演算子は結果が真であれば整数1を、偽であれば0を返します。
これらの演算子は文字列に対しても正しく機能します。値の大小は辞書順比較で決定されます。 論理の真偽は以下で判断されます。
偽 整数0、実数0.0、空の文字列、空の汎用配列
真 上記以外のすべて

代入でない演算は結果がそのまま出力となります。

foo
{
    (3+2)*4
}

この関数fooは20を出力します。

同じ優先度の演算子が連続している場合は、常に左から結合されます。

1+2-3

たとえば上の式は

  1. 1+2
  2. 3-3

の順に計算されます。

i = j = 10

これはどうなるでしょう。C言語では代入演算子は右から結合されますから、iとjには10が代入されます。
しかし文では結合は常に左からです。すなわち

  1. i = j
  2. j = 10

の順に計算されます。したがって、iには10は入らないのです。

i = (j = 10)

これで i にも10が入るようになります。

演算対象の項の型が一致していない場合、結果の型は以下のようになります。

  • 整数と実数の演算
    結果は実数となります。
  • 整数/実数と文字列の加算
    数値は文字列に変換された後、もう一方の文字列に結合されます。
  • 整数/実数と文字列の大小比較
    数値は文字列に変換された後、辞書順で大小比較されます。
  • 整数/実数と文字列の演算(加算・大小比較以外)
    演算不能ですがエラーとはなりません。結果は空の文字列となります。

ひとつの演算式内で型が混在していても構いません。
必要に応じて、上記の法則により型変換が起こります。

"10+2は" + (10+2) + "です。"

最初に10+2が整数として計算され、結果12が得られます。残りはすべて文字列との加算ですから、12は文字列に変換され、文字列として結合されます。

ブラケット( )による演算順序制御

ブラケット( )で囲んだ部分は演算順序が最優先扱いになります。
( ) はいくつでも重ねて指定可能で、深くなるほど優先度が上がります。 平たく言えば「かっこで囲んだところを先に計算する」ということです。これは当たり前の規則なのでいまさら大きく扱うまでもないのですが、 数式の書き方によってはなかなかややこしいこともあります。
以下の例を見てください。

answer = (_i = 10) + (2*(_i + 10))

文の演算則をよく理解している人でないと、answerに何が代入されるかを正確に答えることは出来ないでしょう。
answerには文字列の"10"が入ります。決して整数50ではありません。 最初に計算されるのはどこでしょう。ブラケットが一番深いところ、すなわち _i + 10 です。さて変数 _i はまだありません。したがってこれは空の文字列になります。となると、_i + 10 は文字列と整数の加算です。10は文字列に変換され、"10"となります。しかし次が整数との乗算なので、結局また空文字列になってしまいます。
ここまで説明すれば結果が文字列の"10"になる理由は明白でしょう。 さて、こちらの意図ではまず_i = 10の代入を先にしてもらいたいわけです。
このような場合、文では以下のようにブラケットを過剰に付与することで演算順序をコントロールします。

answer = (((_i = 10))) + (2*(_i + 10))

これで代入部分の優先度が一気に引き上げられました。今度は正しい結果が入るはずです。 なお、代入部分を囲むブラケットは2段で十分ではないかと思われるかも知れませんが、それも誤りです。ブラケット2段は_i + 10と同じ深さとなりますが、=と+では優先度が+のほうが高いのです。

フィードバック演算子&

フィードバック演算子&は、他の演算子とは使い方がまったく異なる独特の演算子です。

request
{
    _i = 1
    foo(&_i)
}

foo
{
    _argv[0] = 100
}

関数呼び出しの際に引数として変数を与える場合、その先頭に&を書くことができます。 先頭に&を付けられた変数は、呼び出し先関数の_argvの対応する要素へ関連付けられます。すなわち、_argvを書き換えると、対応する呼び出し元の変数の値も書き換わるようになります。
上の例では、fooを実行すると _i の値が100に書き換わります。 フィードバック演算子は好きな位置にいくつでも使用可能です。

request
{
    foo(1, 2, &_value, "Hello", &_value2)
    
    _value + _value2
}

foo
{
    _argv[2] = _argv[0] + _argv[1]
    _argv[4] = _argv[3] + " World"
}

関数requestは "3Hello World" を出力します。 当然のことですが、フィードバック演算子は変数にしか付けられません。