ソラマメブログ

2007年05月29日

演算子(lsl基礎知識 第三回)

今回は「演算子(えんざんし)」についてのお話です。
演算子というのは、「+」とか「-」とか、計算を行うための記号のことです。
ほとんどは算数と同じですので簡単に理解できますが、一部、プログラムに独特な考え方をするものもあります。
基本演算

いわゆる四則演算をまず片付けましょう。
四則演算+αですが・・・。

演算子意味
+加算。足し算です
-減算。引き算です
*乗算。掛け算です
/除算。割り算です
%余り。割り算した余りを計算します


+と-は算数と一緒ですね。
掛け算は×ではなく*になります。
割り算も÷ではなく/です。この/は分数の横棒のイメージですね(1/4=四分の一、すなわち1÷4)。
%は算数の÷に似ていますが、割り算ではなく余りの計算です。例えば、「10 % 3」ですと、10÷3の余り、1になります。

演算子は変数の型によって使えるものと使えないものがあります。
上記5つの演算子を全て使えるのは、integer型(整数型)の変数です。

integer money1 = 100;
integer money2;

money2 = money1 + 100;
money2 = money1 - 50;
money2 = money1 * 2;
money2 = money1 / 25;
money2 = money1 % 75;

上記は全てOKです。

float型(小数型)も四則演算は使えますが、唯一%(余り)は使用できません。
小数には余りが無いですので(^^;

float speed1 = 0.5;
float speed2;

speed2 = speed1 + 1.0;
speed2 = speed1 - 0.25;
speed2 = speed1 * 1.5;
speed2 = speed1 / 0.1;


string型(文字列型)で使えるのは+だけです。
文字列型で+を使った場合は2つの文字列が連結されます。

string name1 = "pine";
string name2;

name2 = name1 + "apple";

上記の場合、name2には"pineapple"という文字列が入ります。

他の型も合わせてまとめたのが以下の表です。

+-*/%
integer
float 
string    
vector 
rotation 
list    


vectorやrotationの計算結果がどのようになるかについては、ひとまず省略します。

基本演算の応用

四則演算子を代入演算子と組み合わせて使うことができます。
代入演算子というのは「=」のことです。
前回やりましたが、これは「等しい」ではなく、「変数に値を代入する」という意味の演算子です。

スクリプトのコードを書いていると、時として、
「ここで変数の値を10増やしたいんだよな~」
「ここで変数の値を15減らしたいんだよな~」
「ここで変数の値を2倍にしたいんだよな~」
「ここで変数の値を半分にしたいんだよな~」
という状況になることがあります。

これを素直に書くと、

integer money = 100;
money = money + 10;
money = money - 15;
money = money * 2;
money = money / 2;

こんなふうになります。
moneyの値を足したり引いたり掛けたり割ったりして、もとの変数moneyに代入(値を書き換え)しています。
ま、要するに、moneyの値を10増やしたり、15引いたり、二倍にしたり、半分にしたりしているわけです・・・。

これを簡単に書く方法があります。

integer money = 100;
money += 10;
money -= 15;
money *= 2;
money /= 2;

これらはそれぞれ、
・moneyの値を10増やす(money += 10;)
・moneyの値を15減らす(money -= 15;)
・moneyの値を2倍にする(money *= 2;)
・moneyの値を二分の一にする(money /= 2;)
ということになります。

また、こんな書き方もあります。

integer money = 100;
money ++;
money --;

これはそれぞれ、
・moneyの値を1増やす
・moneyの値を1減らす
という計算になります。
ループ処理などで、変数の値を1ずつ増やして処理したい場合などに登場しますので覚えておいて下さい。

論理演算

論理演算・・・などと言うと異様に難しそうな響きですが、lslの論理演算は単に、
「正しいか、間違っているか」
の計算のことを言います。
「YesかNoか」「真か偽か」という判断です。

具体的には、
「タッチしたアバターがオーナーかどうか」
とか、
「支払われた金額が正しいかどうか」
などの処理を行うときに使われる計算です。

論理演算は、必ず「正しい」か「間違っている」かのどちらかの値を返します。
「正しい」ときの値をTRUEと言います。TRUEは整数値1とイコールです。
「間違っている」ときの値をFALSEと言い、こちらは整数値0とイコールになります。

さて、簡単なのから見てみましょう。

演算子意味書き方説明
==等しいか?name == "miz"nameという変数の値が"miz"ならTRUE
そうでなければFALSE
!=等しくないか?name != "miz"nameという変数の値が"miz"でないならTRUE
"miz"ならFALSE
<小さいか?money < 100moneyという変数の値が100より小さければTRUE
100以上ならFALSE
>大きいか?money > 10moneyという変数の値が10より大きければTRUE
10以下ならFALSE
<=以下か?speed <= 1.0speedという変数の値が1.0以下ならばTRUE
1.0より大きければFALSE
>=以上か?speed >= 0.5speedという変数の値が0.5以上ならばTRUE
0.5より小さければFALSE


「等しいかどうか」のときには「=」ではなく「==」を使いますので注意して下さい。
間違って「=」を使うと、エラーにならない上、ソフトバンク以上に想定外の動きをします。

上の例では、string型やinteger型、float型を使ってみましたが、「==」と「!=」は全ての型で使うことができます。
「<」「>」「<=」「>=」の4つは、integer型とfloat型でのみ使えます。
大小比較は数値じゃないとできませんので、当然と言えば当然ではあります。

ただし、list型で「==」「!=」を使った場合は、ちょっと判定基準が特殊です。
list型の「==」「!=」は、
「listに含まれる要素の数」
が比較されます。

従って、

[0,1,2,3] == [4,5,6,7,8] ・・・要素4つと要素5つなので等しくない、FALSE
["a","b"] == ["c","d"] ・・・どちらも要素2つなので等しい、TRUE
[0,1,2] != [3,4,5] ・・・どちらも要素3つなので等しい、FALSE
["a","b","c"] != ["d","e"] ・・・要素2つと要素3つなので等しくない、TRUE

要素の中身が何であろうと、要素数しか判断基準にしませんので注意して下さい。

論理演算の応用

さて。
ここから難しくなってきます(^^;
基本ではあるのですが、プログラミングに慣れていないと非常にわかりにくい世界に突入しますので、よくわからない場合はサラッと読み飛ばしていただいても構いません。

先ほどは単純な判定でしたが、もっと複雑な判定をしたい場合があります。
「タッチしたアバターがオーナーで、かつオブジェクトに座っている場合」とか。
「SIMが昼間か、または周囲に5人以上の人がいた場合」とか・・・。
そういう場合はどのようにするのでしょうか。

複数の判定条件がある場合は、それぞれに判定を行います。
それぞれの論理演算は結果的にTRUEかFALSEにしかなりませんので、あとはTRUEとFALSEの組み合わせで最終的な判定を行います。

判定条件が二つだった場合を想定して、どのように書くか見てみましょう。
仮に、一つ目の判定条件をA、二つ目の判定条件をBとします。
A,BはどちらもTRUEかFALSEの値になりますので、組み合わせは4通りです。
それぞれの値の組み合わせに対して、以下のような演算子で判定を行うことができます。

演算子書き方説明Aの値Bの値結果
&&A && BAND演算。両方TRUEのときにTRUE
どちらか一方でもFALSEの場合はFALSE
TRUETRUETRUE
TRUEFALSEFALSE
FALSETRUEFALSE
FALSEFALSEFALSE
||A || BOR演算。どちらか一方でもTRUEのときにTRUE
両方ともFALSEの場合はFALSE
TRUETRUETRUE
TRUEFALSETRUE
FALSETRUETRUE
FALSEFALSEFALSE


かなりややこしくなってきましたw
具体的に見てみましょう。

string型の変数nameが"miz"で、かつinteger型の変数countが10以上の場合にTRUEとする判定は・・・。

まず二つの判定を分けます。
「name == "miz"」

「count >= 10」
ですね。

両方ともがTRUEのときにTRUEとしたいので、 「&&」を使います。

(name == "miz") && (count >= 10)

このようになります。

さらに複雑にしてみましょう。

変数nameが"miz"で、かつ変数countが10以上の場合か、またはfloat型の変数speedが0.5より小さい場合にTRUEとする判定は・・・。

先ほどと同じく、
「name == "miz"」と「count >= 10」
これに加えて、
「speed < 0.5」
という判定が追加されます。

「変数nameが"miz"で、かつ変数countが10以上の場合」は、
  (name == "miz") && (count >= 10)
こうでしたので、さらに、
「または変数speedが0.5より小さい場合」
を「||」でつなぎます。

( (name == "miz") && (count >= 10) ) || (speed < 0.5)

こんなふうに、()でくくって「&&」や「||」でつなげていくことで、複雑な判定を行うことができます。
()の位置には気をつけてください。
位置を間違えると、判定の意味は大きく変わってきます。

例えば・・・。

(name == "miz") && ( (count >= 10) || (speed < 0.5) )

これは先ほどの判定式と似ていますが、()の位置が異なります。
この判定はどのようなものになるかというと、
  (name が "miz") かつ ( (count が 10以上) または (speed が 0.5より小さい) )
ですので、
  変数nameが"miz"の場合で、かつ、countが10以上かspeedが0.5より小さい場合
になりますw

・・・言葉で書いてもわけわかりません(^^;
「&&」と「||」は、慣れると複雑な条件判定を一行で書けるのですが、判定式がたくさん出てくると非常にややこしくなってきますので、最初は二つの判定式をくっつけるところから練習すると良いかも知れません。

最後に、もう一つ論理演算子を紹介しておきます。
否定の演算子です。

!(name == "miz")
!(name != "miz")
!(count < 10)
!(count >= 5)


「!」は否定を意味します。
TRUEならばFALSE、FALSEならばTRUEを返す演算子です。

上記の例は、
  !(name == "miz")・・・nameが"miz"と等し「くない」=nameが"miz"と異なる
  !(name != "miz")・・・nameが"miz"と異な「らない」=nameが"miz"と等しい
  !(count < 10)・・・countが10より小さ「くない」=countが10以上
  !(count >= 5)・・・countが5以上「ではない」=countが5より少ない
ということになります。

なんだかウソツキ族とショウジキ族を相手にしているような気分になってきます(^^;
まあ、この辺りは少しずつ身につけて行けばいい部分だとは思いますが・・・。

このような複雑な論理演算ですが、lslでは主にif文という条件判定文において使われます。
リクエストもありましたので、次回はif文の説明なんぞしてみたいと思っています。

ではまた。


この記事へのトラックバックURL

http://miz.slmame.com/t7447
この記事へのコメント
1,2,3回を拝見しました。
すばらしいです。
ここまで丁寧に解説しているところは見たことありません。
私もMakapuさんのこのスクリプトの記事を読んで
”やってみようかなぁ”という気持ちになりました。

「間違って「=」を使うと、エラーにならない上、ソフトバンク以上に想定外の動きをします。」
は最高ですww。
Posted by ポイキチ at 2007年06月05日 13:00
>ポイキチさん

スクリプトはSLの中でも敷居が高い部分かもしれませんが、興味のある方が最初の敷居を越えられるよう、試行錯誤しながら書いています。
一つめを越えても、第二、第三の敷居がまたあるんですけどもねw

全ての人がスクリプトに熟達することは有り得ないでしょうが、「面白い」と思った人なら先に進みたくなるはずです。
面白いかどうかは一歩入ってみないとわかりませんので、やはり最初の敷居は低くしておかないとですね(^^
Posted by Miz at 2007年06月06日 11:36
本当にすばらしい解説で解りやすいです。
おかげさまで少しではありますがスクリプトを書くことが出来るようになりました。
文章もユニークでついつい読みたくなってしまうほどです。
本当ソフトバンク以上には笑いましたw
でも考えてみたらソフトバンクは想定外じゃなくて予想外だったような・・・w
本当にここ以上に解りやすい所無いってくらい最高です!ありがとうございます!
Posted by ウリボウ at 2007年06月19日 03:50
>ウリボウさん

そうですね、予想外が正解です。
勢いで書いてそのままにしてました。
どっちでもいいやと思ったので・・・(^^;

そんなところに2度もコメントが付くとはまことに予想外でした。
Posted by Miz at 2007年06月20日 19:40