計算してみよう

数値演算、複合代入演算子、++、--、trace()


今まででタイトルが一番ストレートなAS講座第06回です。
タイトルの通り、今回は計算をしましょう。
ダン☆おににも使われてることはすぐにわかりますね。
表向きに数字がでるのは得点計算くらいのものでしょうが、
例えば速度変化などにもいろんな計算が必要なのはすぐ想像できるでしょう。
今回は、前回の変数の話を絡めながら、そういう計算のことを扱います。

その前に。

前回、変数の中身を表示するのに、
その変数に対応したテキストを置く方法をとりました。
が、意外とめんどくさかったと思います。
そこで、変数の中身を見るもう1つの方法をお教えします。
そして今回はそっちを使ってみることにしましょう。

それが、trace()というものを使う方法。
かっこの中には変数名を書いておきます。

すごく簡単なので、実際にやってみた方がはやいと思います。
スクリプトを置いて、次のように書いてみましょう。




そしてプレビュー。

これで、中身が見えたのわかりました?

え?わからない?

・・・ですよね。
どこに中身が表示されたのかわからないんですから。

表示された場所は、フラッシュの中ではありません。
キーボードの上の方にある、F8というキーを押してみてください。
何か変なウィンドウが開いたと思います。
メニューの「プレビュー→トレースウィンドウを表示」でも開けます。

ウィンドウの名前はトレースになっていて、そこには3という数字が。
trace()という命令は、かっこの中のものを
このトレースウィンドウに表示しろ、という命令です。


この窓を開きっぱなしでもう1回プレビューしてみましょう。
3というのが増えたのがわかりますか?
一行目で代入する数字を変えれば、その数字が出ます。




以下、計算のことからちょっと離れて(って、まだ始まってもない気もしますが)
trace()の基本。


まず、trace()は、変数の中身を表示するだけじゃありません。
trace(3);
と書けば、変数とか関係なく、トレースウィンドウに3と表示できます。
文字も同じようにいけますよ。
trace("OK");
でトレースウィンドウにOKと出ます。
文字列ですから、""でくくるのを忘れないでくださいね。
何の意味があるのか今は分かりづらいかと思いますが、
その部分のスクリプトがちゃんと実行されているかどうかのチェックに使います。
主にバグが出たときに原因を探すのに役立ちます。

それから、trace()は、プレビューの時しか意味がない関数です。
普通にSWFを見るときにはトレースウィンドウなんてないんですから。
なので、SWF生成をするときには、このtrace()という命令は無視されます。
ですから、これを使ってもSWFが重くなるということはないので安心してください。

と言っても、1秒に100個とか、大量にtrace()されたりしても人間じゃ読めませんし、
どれが目的とした変数の中身なのかもわかりません。
そもそもプレビュー用のSWFは重くなるので、
実際に何かの作品中でtrace()を使う場合は、
変数の中身のチェックが終わって用済みになったtrace()は極力削除しておきましょう。




さて、trace()の使い方もわかったところで、計算してみましょう。
計算といっても、微分の計算とか、三角関数の計算とか、
そういうことをするわけではありません。
今回やるのは、せいぜい四則演算(加減乗除)ともう何種類か、くらいです。


まず、下準備として、ParaFla!で新規作成をして、
右ペインにアクションの挿入で<スクリプト>を置きましょう。
そして、トレースウィンドウを表示しておきましょう。
今回はひたすらこれを使います。
何かを表示するものではないので、プレビューSWFでは何もおきません。
トレースウィンドウに何が出るかが大事。



では、足し算からやってみましょう。
スクリプト部分に次のように書いてみましょう。
はじめのうちはできればコピペなんて使わずに自分で書いてくださいね。
trace(3+2);
ちゃんと5って出ましたか?
3+2を(計算してから)表示しろと命令したわけですから、
5と出るのは当然ですね。
5+3とか、8+7とか、1+2+3+4+5とか、いろいろ試してみましょう。
足し算に飽きたら次へ。



次は、引き算です。
次のように書いてみましょう。
trace(5-3);
ちゃんと2って出ましたか?
この減算記号は、負の数の表記にも使えます。
-1-2とか、-1-(-2)とかも計算できますよ。



あ、そうそう、中を先に計算しろ、というかっこは
数学と同じように使えます。
ただし、数学と違うのは、何重に重ねても普通のかっこを使います。
trace(-1-(-2)-(-3-(-4)));
こんな感じ。
ちょっとややこしいですが、
普通に使ってたらこんなに重なることはないので安心してください。
それでももしこんなことになってしまったら、
trace( -1-(-2) - (-3-(-4)) );
とか、うまくスペースを空けるとみやすいかもしれません。
また、かっこの開閉の数が合ってない場合は構文エラーで見つけてくれるので、
複雑な計算式を書いたときには構文チェックをしてみましょう。



さて、掛け算です。
「かける」を変換して出てくる×という計算記号は
日本語の文字扱いなのでASでは使えません。
じゃあ何を使うかというと、*を使います。
「+」の隣にある、「:」とか「け」とかあるキーを、
Shiftキーを押しながら押してください。
半角で使ってくださいね。
trace(2*3);
6って出ましたか?
ちなみに、ちゃんと乗除は加減より先に計算してくれます。
trace(1+2*3);
で7と計算してくれますよ。



4つめ、問題児の割り算です。
掛け算と同じく÷は使えないので、/を使います。
「+」や「*」のすぐ下にありますよ。

trace(20/5);
trace(5/2);
4と2.5って出ましたか?
整数の答えにならない場合は、小数で答えをだします。
とまあ、ここまではいいんですが、問題児と書いた理由は次。
割り切れないときは、十数桁までで計算を打ち切ります。
trace(20/3);
とかやってみてください。
最後、切り上げて7になって計算終わってますよね。
このように、割り切れない割り算は微妙に誤差が出るので注意してください。
1/3と2/3を足したら1.000000000000001になったりすることがたまーーーにあります。
ほとんど違わないんで大抵は影響がないんですが、
1例だけこれがモロに影響する場合があるんです。
次回いきなりそれがでてくるので、その時に解説します。



さて、これで四則演算全て出揃いました。
が、プログラミング言語の世界では、
これらと並んで大事な計算がもう1つあります。
それが、%という計算。
「5」のキーをShiftキーを押しながら押してください。
パーセントですが、「100%が1だ!」とかいうものではありません。
この計算記号だけは、小数には使えません。
整数%整数でしか使えない記号です。








Problem


%がどういう計算なのか、当ててみましょう。

まずは%が計算記号であることを確認するため、
5%2とか、6%4とかをトレースウィンドウに出力させてみましょう。

できたら、いろいろ数字を変えて、%の意味を当ててみましょう。

どうしてもわからなかったら、
%10とか%100とかで前の数字を変えまくってみると
わかりやすいかもしれません。

なんとなく想像が付いた人、ずっと粘ったけどわかんない人は答えをどうぞ。

答え(反転):前の数字を後の数字で割った余り

計算の優先順位は掛け算や割り算と一緒です。
掛け算や割り算と並んでたら左から計算し、
足し算や引き算よりは先に計算します。








これで、5種類の基本の数値演算がそろいました。
他にも&とか|とか>>とかいう計算もありますが、
そういうのはまたの機会にってことで。


あ、でももう一つだけ覚えてほしいものがあります。
それは、+という計算。

あれ?さっきやったような。
そう、さっきと同じ記号です。
が、こいつにはもう1種類の意味があるのです。
それは、文字列の連結。
+の前後が数字だったら、その2つの数字を足します。
が、+の前後が文字列だったら、その2つの文字列をつなげる記号にはやがわり!
trace("おはよう"+"ございます");
で、"おはようございます"という計算(?)結果が出てきます。

それに関連して、よくやる間違い。
trace("1"+"2");
これ、計算結果は何になると思います?

文字列の"3"?

いえいえ、違います。正解は"12"。
この"1"は、数字の1ではなく、文字の"1"です。
"2"も同様。
ということは、この+は数字を足す+ではなく、文字列を連結する+だと判断されて、
計算結果はその文字列を連結した"12"になります。注意してください。
trace("1"+2);
みたいに、文字列と数字を足したら、はてさてどうなるでしょうね。
あるいは数字+文字列と順番が逆だったら。
自分で試してみてください。








で、基本の計算全部そろっちゃったから、今回これだけで終わり?

いいえ、とんでもありません。

最初にこういいましたよね。
前回の変数の話を絡めながら計算のことを扱う、と。
今は計算してトレースウィンドウに出力しただけ。
これが、前回の代入の話と合わさると、いろいろ話が広がるのです。








まず、計算して代入、というものからやりましょうか。
いままで、代入といえば、右辺のものを左辺に代入、というものでした。
が、右辺に計算式を持ってくると、右辺の計算をした結果を左辺に代入、になります。

_root.a=3+2;
trace(_root.a);
こうしたら、トレースウィンドウに5と出ますね。
ちゃんとaに計算結果が代入されているようです。
え?簡単すぎる?

では、いきなりステップアップして、こんなことしたらどうでしょう。









Problem

10行まとめて書いて実行した場合、
6回のtrace()で、順に何が表示されるでしょうか。

_root.a=3+2;
trace(_root.a);
_root.a=5+4*3%5*2;
trace(_root.a);
_root.b=_root.a+2;
trace(_root.a);
trace(_root.b);
_root.a=_root.a*3+2;
trace(_root.a);
trace(_root.b);
正解は、このASをコピペして実行してみればわかります。
何の問題もなく正解した人は解説を斜め読みだけして次へどうぞ。


---------------解説ここから---------------


まず最初、
_root.a=3+2;
で、aに5が代入されます。そして
trace(_root.a);
でaの中身である5がトレースウィンドウに表示されます。
ここまではさっきやりましたね。
で、次です。
_root.a=5+4*3%5*2;
今度は計算結果は9なわけですが、計算できましたか?
まず、4*3で12、次に12%5で2、その後2*2で4ときて、最後に5+4で9になります。
こういう計算で例えば自分が「4になるはずだ」と思い込んでたりすると、
このaを使った先の計算結果が全部思ってたのと違うってことになりえるんで、
自分が計算間違いというのは絶対にしないようにしてくださいね。
で、計算結果の9をaに代入しました。
今まで入ってた5はどこかへ消えました。
trace(_root.a);
当然ここでaに入っているのは9ですね。
_root.b=_root.a+2;
今度は新しいパターンです。
こんなことも出来るんですね。
想像の範囲内ですか、そうですか。
aの内容に2を足したものをbに代入します。
今aに入ってるのは9でしたから、
ここでbに11が代入されます。

trace(_root.a);
trace(_root.b);
ここで間違えた人、いるんじゃないでしょうか。
さっき、aの中身に2を足してbに代入しました。
ここで注意しなくちゃいけないのは、
aの中身が2増えたわけではないことです。

ですから、aの中身はさっきのまま9、bの中身は今代入した11です。
_root.a=_root.a*3+2;
今度はさすがに「えっ!?」と思った人、多いんじゃないでしょうか。
a=3a+2だったらa=-1かな・・・?
違います。
あくまで、=という記号は、等式の記号ではなく、代入しろという命令なので、
aに3をかけてから2を足し、その結果をa自身に代入しろ、ということです。
今aには9が入ってますから、それを3倍して2を足した29がaに代入され、
さっき使ったばっかりの9という数字はどこかへ消えてなくなります。

trace(_root.a);
trace(_root.b);
途中でb=a+2なんていうのが出てきましたが、
その後でaの中身が変わってもbの中身はそのままです。
なので当然29と11が出てきます。

途中の複雑なやつで「4になるはずだ」と思ってた人は、
「最後に14と6になっているはずだ」、と間違えます。
1つのミスで2つとも間違ってます。
このように、計算ミスや勘違いはどんどん拡散するので気をつけましょう。



---------------解説ここまで---------------


ゲームの中では、もっと多くの変数(とか配列とか)が、
めまぐるしく中身を変えつつ動いています。
もちろんダン☆おにも例外ではなく、
どんなソースを見ても、常に100以上の変数(とか配列とか)が存在し、
ASに従って次々と書き換えられていきます。

ゲーム内に存在する変数全てを同時に把握していなければ、
なんてことはまずありませんが、
それでも、どんな小さな挙動でも、書き換えるもの、中身を見るだけのもの、
あわせて10個程度の変数は絡んでくると思います。
(今の練習問題では2個でしたが、こんな少ないことはほとんどないでしょう。)

どの変数がどういう意味をもっているのかはもちろんですが、
それらがいつどこでどんな時に書き換えられているのか、
どんな時は書き換えられないのか、
書き換えられるときにはどんな値に書き換えられるのか、
いじった部分が他の部分にどう影響するのかをきちんと把握していないと、
ちょっと一行いじったらゲーム全体動かなくなったなんてこともありえますから、
こういう変数の挙動は把握できるようにしましょう。
どうやったらできるようになるかはわかりませんが、
慣れは少なくとも必要だと思います。


本当に、こういう「感覚」みたいなものってどうやって伝えたらいいんでしょうね。
まあ、きっと伝える方法なんてないわけで、
こればっかりは自分でつかんでもらうしかないんでしょうね。








さて、これで今回の3つのテーマのうち、2つが終わりました。
まだ1つ残ってますね。
複合代入演算子というのが。

なんか難しそうな言葉です。
言葉を分解してみましょう。

まず、演算子
これは、演算をするための記号のことです。
演算は計算とか処理とかそういうものをまとめて言う言葉ですね。
今まで使ってきた+-*/%というような計算記号たちや、
=というような何かの処理を行うための記号、これが演算子です。

で、代入演算子というのは、
その演算子の中で、代入処理を行うもののことを指します。
すなわち、=のことです。
・・・と言いたいのですが、実は代入演算子には他にも種類があるのです。
=は代入処理だけを行うので、単純代入演算子と呼ばれます。
もうそろそろ先が見えてきましたか?

そう、複合代入演算子は、
特殊な代入方法をするような代入演算子のことを言います。

上の十数行をひとことにまとめると、
複合代入演算子っていうのは=のパワーアップ版だよ!ってことになります。


さて、何がパワーアップしたんでしょう?
何が複合なんでしょう?
なんか難しそうな単語を難しく解説したのでびびってる人もいるかもしれません。
が、非常に単純な話です。
_root.a=_root.a+3;
こんなASがあったとします。
aの中身を見て、3を足した結果をaに戻す。
もっと平たく言えば、aの中身を3増やす計算ですね。

これ見て、何か思いませんか?
いや、何も思わない人はそれでもかまいません。
こうやって書いてもちゃんと動きますから。

ですが、こう思った人はいると思います。
_root.aって2回も書くのはめんどくさいし、見にくいよなぁ。

そうですよね。
それに、これだけ見ても、「aの中身を3増やす計算だ!」とはパッとはわかりにくいです。
そこで、もっとシンプルに書く方法を紹介します。
さっきのやつは、こうやって書くこともできます。
_root.a+=3;
すっきりしました。
+=というのは、右の数字を左の変数の中身に直接足してしまう演算子です。
足し算という演算と代入演算を同時に行う、
そういう代入演算子なので複合代入演算子と呼ばれます。


足し算だけじゃありません。
例えば掛け算。
_root.a*=_root.b;
と書けば、aの中身を_root.b倍することができます。
もちろん、
_root.a=_root.a*_root.b;
と同じ結果になります。

他にも、-=や/=だけでなく、%=なんてものも用意されています。
さすがに%=はめったに使う機会はなさそうですが。
それから、+で文字列の連結という演算もできたように、
+=は、文字列の追加というのをできます。

_root.aisatu="おはよう";
trace("_root.aisatu="+_root.aisatu);
_root.aisatu+="ございます";
trace("_root.aisatu="+_root.aisatu);
これを実行すると、最初に"おはよう"だったものに
"ございます"が後ろに追加されて、
aisatuの中身が"おはようございます"になるわけですね。
ただし、これとは逆に前に文字列を追加する複合代入演算子はありません。
そもそも、そんなのはあったとしてもめったに使いませんからね。

あと、trace()のところで変数以外に何か書いてますね。
最初にtrace()のことを書いたときには混乱するとまずいので書かなかったのですが、
trace()で中身を見るときは、何の変数の中身なのか分かるようにするために、
trace("変数名="+変数名);
と書くのが普通です。
""の間は文字列なので、1つめの変数名は、
そういう名前の変数が存在するかどうかと関係なく、そのまま出てきます。
なので、実は変数名そのままじゃなくても
自分がどの変数か分かるように書けばいいんですけどね。








おまけ。
といいつつ、実は複合演算子よりこっちの方がよく使うんですが。
_root.a+=1;
と書いたら、どういう計算か、わかりますね?
そう、aの中身を1増やす演算です。
が、この1増やすやつはめちゃくちゃよく使うので、
さらに別の特殊な書き方が用意されています。
その書き方がこちら。
_root.a++;
いかにも増えそうな感じがします。
字数的には1文字しか変わってませんが、
いろんな文字が混ざってたのがなくなったおかげでかなり見やすいです。
この++で1増やすことを、インクリメントといいます。
前に書いてもいいです。
++_root.a;
というか、普通はコンピューター言語では前に書きます。
というのも、そっちの方がほんの若干計算が速いのです。
が、ASの場合、変数の前にパスが付くので、前につけると非常に見にくいため、
後ろにつけることのほうが多いです。

あ、そうそう、インクリメントの反対もあります。
_root.a--;
aの中身が1減ります。いかにも減りそうです。やっぱり前に書いてもいいです。
この--で1減らすことを、デクリメントといいます。
どちらも非常によく使うので(特に++の方)、
覚えておいて損はないというか、覚えておかないと損します。








Problem

9行まとめて書いて実行した場合、
最後のtrace()で、何が表示されるでしょうか。
見やすさ重視のためthisは全て省いてあります。
実際に使う時にはこういう書き方はもちろん非推奨ですよ。

a=3;
b=3;
a+=b;
b+=a*a-1;
a--;
b%=a;
trace("a="+a);
trace("b="+b);
trace("a+b="+a+b);
正解は、このASをコピペして実行してみればわかります。
thisが補完されるのできちんと計算結果は出てくれます。
解説は用意しません。
間違えた人は、計算途中にtrace()をはさんでみて、
どこから勘違いをしたのか探してみましょう。
ひっかけ注意。









Training



今までのProblemより絶対こっちの方が役に立ちそうです。

変数の中身表示用のテキストを1つ用意。
さらに、ボタンの絵をParaDrawを使って4つ用意して、
それぞれに「+1」「-1」「×2」「÷2」と書いてください。

1フレーム目で、何か適当な変数に1を代入。
2フレーム目で、その変数を表示するテキストと、
4つのボタンを配置。そして「停止」

ボタンに何を書くかは言わなくても分かりそうですが、
ボタンを押したときに、表示されてる数字が
ボタンに書いてあるとおりに変化するようにしてください。









以上、複雑な処理の第2歩目のAS講座第06回でした。
今回の内容だけやっても何も面白くなかったかと思いますが
次回からはまた面白くなります。きっと。
そのためにも、今回の内容はきっちり理解しておいてくださいね。









PlusOne:な、NaNだってー!!!



trace()でいろいろ中身を覗いていると、たまに変なものが出てくる時があります。
そのうち主なものが、NaNundefinedだと思います。
こいつらは一体なんなんでしょうか。

まず、undefinedの方ですが、これは英語の意味から考えればすぐに分かります。
defineが「定義する」で、それの過去分詞に否定の接頭辞unがついたのですから、
「定義されていない」ということになります。
ようするに、「そんな変数ないよ」ってときに返ってくるのがundefinedです。
ただし、厄介なのは、trace()でundefinedが帰ってくるのは、
trace()で中身を見ようと思った変数がなかった場合だけではありません。
そんな名前の変数がないような変数の中身を代入しようとした場合、
変数はあるけど中身はundefined、という状態になります。
そうなれば当然、trace()で返ってくるのはundefinedです。
また、片方がundefinedなもので足し算した結果とかもことごとくundefinedになります。

ということは、trace()でundefinedが返ってきた場合、どう理解すればいいかというと、
その変数がなかったか、最後にそれに代入した変数がなかったか、
あるいはその代入した変数に代入した変数がなかったか、以下省略、
またはそういうところで計算の一部に含まれた変数がなかったか・・・

ということになります。
・・・がんばって原因を探してください。



さて、最初にもう1つ挙げましたね。
NaNというやつ。
これは、Not a Numberの略です。
「数字じゃない」ってことですね。
どういうことかというと、例えば引き算。

a=3;
b=2;
c=a-b
cには1が代入されます。普通ですね。
では、これはどうでしょう。

a="DANCING";
b="ONIGIRI";
c=a-b
1行目と2行目は普通に実行されますが、3行目で困ります。
"DANCING"から"ONIGIRI"を引き算・・・?
できませんね。数字じゃないのですから。
こういうときに、cの中身に
「数字じゃないから計算できないエラーが起きたよ!」って意味でNaNが代入されます。

trace("a"-"b");
とかやればすぐNaNが返ってくるのは見れます。
-*/%全部数字限定の計算ですからね。
+だけは文字列の連結として普通に計算できるので、
普通に連結した結果が返ってきます。

おまけ。

パソコンは、正しくない計算式の場合でも、
なんとかがんばって計算してくれようとします。
例えば、
trace("c"-"b"+"a");
とかやると、最初の2つの計算でNaNになり、
そのあと文字列のaを足すのは文字列の結合で無理矢理計算されて、
"NaNa"とかいうすごい結果が出てきます。
別に計算結果が7だったわけじゃありません。

まあ、この場合はエラーの後無理矢理計算したなってすぐにわかるのですが、
もっとたちが悪い例があります。

a="1";
b=(a+2)*3;
trace(b);
最初のaへの代入が、数字だと思ってたのが実は文字列でした。
これ、どうなると思います?

やってみればわかります。
36が返ってきます。一切エラーしません。
文字列の中身が数字の場合は、
+の場合は普通どおりの計算として文字列の連結をし、
-*/%の4種の記号が来たら、その文字列を数字だとみなして
がんばって答えを出してくれます。

が、がんばって答えを出せてしまうがゆえに、何らエラーしません。
このASを書いた人はaにはちゃんと9が入ってるつもりで、
エラーもしないのに、何かおかしい、という事態になります。
で、原因をよくよく探してみたら、9だと思ってたところが実は36だった、というわけですね。
「そんな、数字をわざわざ文字列として代入とかしないって」
と思ってても、ダン☆おにでは、とある改造をするときによくこのミスをします。
それは、読み込んだ譜面データをいじろうとした場合ですね。
読み込んだ譜面データの、カンマで区切られてるのを分割した後にでてくる数字は
実は全部、中身に数字が入ってる文字列です。
ゆえに最初に足し算をすると変な結果になります。

そういう文字列で普通に数字として足し算をしたい場合は、
Number()というのを使ってください。


a="1";
a+=2;
b=Number(a)+3;
trace(b);
これは15という結果が返ってきます。
2行目では文字列の結合が計算されて、aの中身は文字列の"12"になります。
Number()というものは、そのかっこの中の変数の中身が、
数字が入ってる文字列だった場合、それを数字とみなして計算できるものです。
だから、3行目は数字としての12+3になって、15になるわけです。
ただし、気をつけなきゃいけないのは、一時的にそうみなしただけであって、
aの中身はまだ文字列の"12"です。注意。

たかが足し算と思いきや、意外と難しいもんです。










PlusOne:おすすめできない計算式



実は、今回扱った演算子の中で、
本編で「こんなこともできるよ!」というのを紹介しなかったのが2つあります。
何故紹介しなかったかというと、間違えやすいのでおすすめしないからです。

それでも、何かの役に立つこともあるかもしれません。
一応その2つもここで紹介しておきます。
あくまでもおすすめしない計算式ですよ。


まず1つめ、インクリメント演算子、デクリメント演算子について。
++とか--とかいうやつですね。
前に書いても後に書いてもいいってことですが、
よく考えるとなんか変ですよね。
どうせ同じものなら、こっちに書いてくださいってことにすれば、
みんなそれに従うでしょうに。

それに対する答えは、単純です。
ある使い方をした時に限り、前と後ろで効果が違うから
わざわざ両方あるのです。

++というのは、実は式の途中でも使うことができます。
たとえばこんな感じ。

a=10;
b=++a*2;
trace("a="+a+" b="+b);
最初にaに10を代入します。
そして問題は2行目。
bにaの2倍を代入しつつ、aを1増やす。

これ、aは11になりそうですが、bにはいくつが入るでしょうか?

aを増やしてから2倍を代入するなら22?
2倍を代入してからaを増やすなら20?
増やしつつ、だからその間をとって21くらい?
いや、2倍した後で代入の前に1増やすのかも、その場合計算結果も1増えるのかなぁ?
・・・よくわかりませんね。
最後の2つははずれっぽいなって感じがしますが。


実は、この1番目と2番目の違いが、前に書くか後ろに書くかの違いです。

a=10;
b=++a*2;
trace("a="+a+" b="+b);
の場合、前に++がついてるので、全ての計算より先にaが1増えます。
なので、bには11*2で22が代入されます。

a=10;
b=(a++)*2;
trace("a="+a+" b="+b);
の場合は、後ろについてるので、全部の計算が終わってから最後にaが1増えます。
なので、bに10*2で20が代入された後でaが11になります。
かっこがついてるので先に1増やしそうな気がしますが、そうではありません。
かっこはわかりやすくするためにつけただけです。
前に書くなら、=の直後とかでない限りかっこが必要ですが、
後ろの場合はかっこはなくても大丈夫です。

とまぁ、ややこしいですね。
プロにとっては実はこっちの方が楽だったりするらしいのですが、
我々のようなシロウトでは混乱するのがオチなので、使わない方が無難です。

a=10;
a++;
b=a*2;
trace("a="+a+" b="+b);

a=10;
b=a*2;
a++;
trace("a="+a+" b="+b);
と、計算順序がわかりやすいように書きましょう。

あと、++を後ろに書いた場合、
左辺にあるのが同じ変数だと、インクリメントされません。

a=2;
a=++a*2;
trace("a="+a);
はちゃんと6になりますが、

a=2;
a=a++*2;
trace("a="+a);
は5ではなく4になります。
代入演算のおかげで「あとで1増やす」という情報が消えてしまうからでしょうかね?
いずれにせよ、++は途中では使わない方が無難そうです。


2つめのおすすめできない計算式。多重代入。
代入演算子は、1つの式で複数使うことが出来ます。
その場合、右から順に処理されます。
最右辺以外は代入演算子の左辺になっているので、
ただ変数名を書く以外のことをすると構文チェックでエラーが出ます。
a=b=c=2
こう書くと、まず一番右の=が実行されて、cに2が代入されます。
次に真ん中の=が実行されて、bにcの中身である2が代入されます。
最後に左の=が実行されて、aにbの中身である2が代入されます。
結局全部2になります。

とまあ、これだけ見ると別にややこしいことはなさそうですが、
複合代入演算子が入ると、とたんにえらいことになります。

b=2;
a=b+=2;
trace("a="+a+" b="+b);
とか、どうでしょうか。
aに入るのはいくつでしょう?
パッと見た感じ2でしょうか?
いえいえ、違います。

まず、右の+=が実行されます。
bが2増えて4になります。
そして、左の=で、aにbの中身の4が代入されます。
あーややこしい。
どう考えても使わない方が無難ですね。




a=b=c=2;
a*=b*=c+++a;
trace("a="+a+" b="+b+" c="+c);
を見て、トレースウィンドウに何が出て来るか、
うろたえることも迷うこともなく"a=16 b=8 c=3"と答えられた人がいたら
私はその人をある意味尊敬します。



おまけ。
これまでに出てきた演算子の優先順位を表にまとめた方がいいのではないか、
という意見を頂いたので、まとめてみました。
上にある演算子ほど先に計算します。
同じ枠にあるやつは、同じ優先度で、
その場合どちらから計算するかは右の枠を参照。
かっこがある場合はその中を先に計算しますが、
++と--を後にかいたやつはかっこの中にあっても最後になります。


++ --(前に書いた場合)  
-(マイナス記号)  
* / % 左から順に
+ -(引き算) 左から順に
= += -= *= /= %= 右から順に
++ --(後に書いた場合)  


気が付けば今回もサンプルソース配布を1つもしてないような。





戻る   掲示板へ