こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

優先順位の概念について質問

質問1:優先順位や結合の規則とは、本質的に「優先順位の高い演算子ほど、オペランドをより先に結び付けられる」であり、「演算実行の優先順位」ではありませんよね?
何故そう思ったかというと次の論理式をご覧ください。

a==1 && b==0 || a==1 && b==0
※int a==1,b==0


この論理式がtureになるプロセスとして、

a==1を評価→true
   ↓

b==0を評価→true


&&は、a==1 && b==0の論理式をtrueと評価


||は、左側の論理式a==1 && b==0がtrueだから、論理式全体がtrueだと判断し、
右側の論理式の評価を行わない。

プロセスとして、こうだと思うんですけど、優先順位として||は&&より低いですよね?
優先順位が「演算実行の優先順位」を意味するならば、右側の論理式のa==1 && b==0を評価してから||の演算をするはずで矛盾します。

よって、優先順位とは本質的に、「優先順位の高い演算子ほど、オペランドをより先に結び付けられる」であり、「演算実行の優先順位ではない」といえる。



質問2:「優先順位の高い演算子ほど、オペランドをより先に結び付けられる」であれば、例えば、上記の論理式の左側を例に挙げていえば、
b==0は&&と||の2つが共有してるが、&&の方が優先順位が高いから、b==0を先に結び付けてる、その意味でも「優先順位の高い演算子ほど、オペランドをより先に結び付けられる」
は正しいですか?

投稿日時 - 2011-07-11 14:26:49

QNo.6868711

すぐに回答ほしいです

質問者が選んだベストアンサー

#1です。

「優先順位が「演算実行の優先順位」を意味するならば、右側の論理式のa==1 && b==0を評価してから||の演算をするはずで矛盾します。」

ここを言っていませんでした。

確かに仰るとおりなら、評価の順番としては矛盾しています。

でも、それなら

「優先順位の高い演算子ほど、オペランドをより先に結び付けられる」

でも同じように矛盾しています。(同じ事を言っているのですから。)

オペランドと先に結びついていませんよね?

式の評価は、「左から右」へ評価するという規則も有るんですよ。
(もちろん逆も有ります。)

&&も||も左から評価する演算子です。

実際の評価順は、

a==1 && b==0 || a==1 && b==0

・a==1を評価「True」
・&&が出てきたので、右も評価
・b==0を評価「True」
・ここで、a==1&&b==1は「True」
・||が出てきた。
・||は左がTrueなら右はFalseでもTrueなので評価は「True」
・後は、より右側の式を見て、優先順位が同じ又は低い演算子が出てこないから終了
(優先順位が高い演算子は、先に演算するべきだけど評価が決まっているから動でも良い。)

みたいな感じなんですよ。判ります?

投稿日時 - 2011-07-11 16:17:48

お礼

丁重なご回答ありがとうございます!
>・a==1を評価「True」
・&&が出てきたので、右も評価
・b==0を評価「True」
・ここで、a==1&&b==1は「True」
・||が出てきた。
・||は左がTrueなら右はFalseでもTrueなので評価は「True」
・後は、より右側の式を見て、優先順位が同じ又は低い演算子が出てこないから終了
(優先順位が高い演算子は、先に演算するべきだけど評価が決まっているから動でも良い。)

みたいな感じなんですよ。判ります?



わかります!
要わ、それは仕様だから仕方ないってことですよね!

投稿日時 - 2011-07-16 02:31:03

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

-広告-
-広告-

回答(6)

ANo.6

実際に実験してみては?
----------------------------------------------------------------------
public class Test {
  public static boolean a() {
    System.out.println("--- a()");
    return true;
  }
  public static boolean b() {
    System.out.println("--- b()");
    return false;
  }
  public static boolean c() {
    System.out.println("--- c()");
    return true;
  }
  public static boolean d() {
    System.out.println("--- d()");
    return false;
  }
  public static void main(String[] args) {
    if (a() && b() || c() && d()) {
    }
  }
}
----------------------------------------------------------------------

実行結果
----------------------------------------------------------------------
--- a()
--- b()
--- c()
--- d()
----------------------------------------------------------------------

投稿日時 - 2011-07-13 01:03:20

お礼

丁重なご回答誠にありがとうございます!
早速実行してみます!

投稿日時 - 2011-07-16 02:32:58

ANo.5

>「優先順位の高い演算子ほど、オペランドをより先に結び付けられる」であり、「演算実行の優先順位」ではありませんよね?

それで正しいでしょう。

ちょっと混乱することを書いて見ます。

a==1 && b==0 || a==1 && b==0

これは、|| の左右で2つに分けられます。式全体の値は、左側を評価して真なら真、偽なら右側の値になるということを、まず認識します。
で、左側を評価すると真なので、それで終わり。

さて、|| の演算はいつ実行されたでしょうか?

投稿日時 - 2011-07-12 00:02:18

お礼

丁重なご回答誠にありがとうございます!

>さて、|| の演算はいつ実行されたでしょうか?

左の式が評価された直後です!

投稿日時 - 2011-07-16 02:32:18

ANo.4

別の演算子の例を見たら分かってもらえるでしょうか。*の結合優先順位は+よりも高いので、"a && b || c && d"と同様の構造になっています。
a * b + c * d
この式の評価は
aを評価 → bを評価 → a*bの乗算を実行 → cを評価 → dを評価 → c*dの乗算を実行 → 加算を実行
のように行われます。

&&と||の例と同様の構造でありながら評価を行う手順が異なるのは、要は、個々の演算子ごとにルールが異なるから。
&&や||はJavaの演算子の中では特殊な評価をするものなので、「そういう風に仕様で決まっている」と覚えてください。
なぜそういう仕様になっているかと言えば、&&は||では右項を評価するまでもなく演算結果が決まる場合があり、そういう場合には右項の評価を省くことで速度が向上するから。
その仕様にご不満ならば、&&や||も必ず右項を評価するような仕様のプログラミング言語をご自分で作ればいいのです。

投稿日時 - 2011-07-11 22:26:44

ANo.2

無理して難しく表現しようとしているようにしか見えない。

「演算子」と「オペランド」を結びつけて結果を求めることを「演算」と言う。

なので、

「優先順位の高い演算子ほど、オペランドをより先に結び付けられる」

とは

「優先順位の高い演算子は、他の演算子より先にオペランドと結びつき演算を実行する」

ので、

「演算実行の優先順位」

は同じ事を言っている。

投稿日時 - 2011-07-11 16:01:43

お礼

丁重なご回答ありがとうございます!

投稿日時 - 2011-07-16 01:35:19

ANo.1

毎度のことながら難しく考えすぎなのか
それともとことん理解したからなのか。

そんなに難しい話じゃないと思うの。
単純明快な規則よ。

・原則左から順に処理する
・オペランドが出現した場合、その左右をオペランドで処理する
・その2つのうち、優先度の高いものがあれば先に処理する

たったこれだけなの。

投稿日時 - 2011-07-11 15:59:20

お礼

丁重なご回答ありがとうございます!


もっとシンプルに考えないといけないですよね、、

投稿日時 - 2011-07-16 01:36:15

-広告-
-広告-

あなたにオススメの質問

-広告-
-広告-