質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.77%

等値と等価のちがいについて

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 14K+

score 578

Javaで開発をしています。
等値と等価の違いについて知りたいと思っています。


等値=同一
等価=同値

ということなのかなあと思っているのですが、合っているでしょうか?

そもそも

同一は、インスタンスが同じこと。==演算子で判定する。
同値とは、インスタンスは違うけれど、値が同じこと。equalsメソッドで判定する。

だと思っています。


調べてみたのですが、個人的な意見を述べているサイトが多く、いまいち自信が持てません。
字面的には組み合わせも逆のような気がするし、調べていくうちにまったくの別物のような気もしてきました。。

有識者の方々よろしくお願いします。

------------------------------------------------------------------------------------------------

追記
このサイトを拝見しました。
http://ryo021021.hatenablog.com/entry/2014/01/02/134232

変数で考えます。等値はそのまま、その変数が持っている値が等しいことです。つまり、以下の式です。[==]を"等価演算子"なんて呼ぶために混乱します。
 
if (a == b) printf("等値\n");
   
   
等価は、昇順にソートする場合等でいう以下の式です。
 
if (!(a < b) && !(b < a)) printf("等価\n");
 
   
 値を、それ自体で比較するのか、論理的に比較するのか、といった感じでしょうか。
   

私の認識は違っていたかもしれません。

等価の「論理的に比較する」の意味がいまいちよくわかりません。
もしアドバイスいただける方がいらっしゃればお願いします。
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

+4

・等値判定(==)はメモリ内の値が等しいかを判断します。
・等価判定(Object#equals)はインスタンスが等しいかを判定します。

int型はプリミティブなのでObjectを継承していません。そのため、メモリ上の値を等しいかどうかに使います。

対してオブジェクトは内部にたくさんの属性を持っています。そのため、Object型を継承しているクラスはインスタンスの比較基準(どの属性が一致していたら同じかなど)をObject#equalsをオーバーライドして決定することが義務付けられています。
オブジェクトが等価かどうかをオブジェクトの特性などから論理的に判断する行為を「論理的に比較する」と表現しているのではないでしょうか。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/10 09:50

    equalsは,デフォルトでは==で比較するのと全く同じ効果となります.
    適切に比較するためには,当該クラスでequalsをオーバーライドして適切な比較処理を記述する必要があります.

    キャンセル

  • 2015/09/10 10:10

    swordoneさん
    回答ありがとうございます。
    そうなんですね。勉強になります。

    確かに自分なりに解釈してequalsメソッドを該当クラスでオーバーライドし、使ったところa.equals(b)が成り立ちました。trueが返ってきました。

    実際に試したのは以下です。



    public class Main {

    public static void main(String[] args) {
    Hoge a = new Hoge();
    Hoge b = new Hoge();
    int c = 0;

    if (a.equals(b)) {
    System.out.println("true");
    } else {
    System.out.println("false");
    }
    }

    }

    class Hoge {
    private int num;

    public int getNum() {
    return num;
    }

    public void setNum(int num) {
    this.num = num;
    }

    public boolean equals(Hoge obj) {
    if (obj == null) {
    return false;
    }
    return this.num == obj.num;
    }
    }


    yonaさん、swordoneさん、勉強になりました。ありがとうございます。


    等値と等価は英語を訳した言葉なので、同値・同一に当て込むのは難しそうですね。。

    キャンセル

  • 2015/09/10 12:10 編集

    ベストアンサーが決まっていますが…

    >・等値と等価の意味
    どうあっても齟齬が出るので
    等値と等価という言葉に固執せずに比較演算子==と比較メソッドequals()として理解することが重要です。

    >・a.equals(b)が成り立つという点。
    swordoneさんの記載通りです。
    勝手な思い込みにより混乱させてしまいました。
    >・a==bが同値判定という点
    プリミティブとインスタンスでは動作が異なります。
    プリミティブは値が等しいかの同値判定を行う。
    インスタンスでは参照値が等しいかを判定しています。
    なので両方とも同値判定をしていることになります。

    キャンセル

checkベストアンサー

+3

間違っていないか不安ですが、自分なりの考えで回答してみます。

例えば、二人の人物を比較するとします。

これを人間(=Humanクラス)として比較するならば、(哲学的には諸説ありそうですが)その「価値が等しい」ことの定義は「全く同じ人物である」ことに他なりません。つまり、Humanクラスにおいて等価の意味は「等値であること」になります。

class Human {
    public boolean equals(Object obj) {
        return this == obj;
    }
}

走者(=Runnerクラス)として比較するならば、その「価値が等しい」ことの定義は走る速さとスタミナで決まるかもしれません。加えて言えば、相手も走者である必要があります。

class Runner extends Human {
    protected int speed;
    protected int stamina;
    public boolean equals(Object obj) {
        if (obj instanceof Runner) {
            runner = (Runner)obj;
            return this.speed == runner.speed && this.stamina == runner.stamina;
        } else {
            return false;
        }
    }
}

短距離走者(=Sprinterクラス)として比較するならばもはやスタミナは問題にならず、その価値はスピードだけで決まるかもしれませんね。比較自体は走者であればだれとでも出来そうです。

class Sprinter extends Runner {
    public boolean equals(Object obj) {
        if (obj instanceof Runner) {
            runner = (Runner)obj;
            return this.speed == runner.speed;
        } else {
            return false;
        }
    }
}

このように二つの物の価値を比べる時に、その評価基準は「それが何であるか」によって変わります。一方で「等しい値である」ことの定義はいつでも同じです。
等値と等価の違いはそこにあるのではないでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/10 11:52

    hy3さん
    回答ありがとうございます。
    タイムラグでコメントの回答がひとつずつズレています。
    申し訳ございません。

    そうですよね。
    なんだか訳語によるミスリードが大きく、回答者によって思い浮かべることが変わりそうな質問な気がします。

    たしかに面談のときは聞き返すようにするといいかもしれませんね。

    少しすっきりしました。
    ありがとうございました。

    キャンセル

  • 2015/09/10 12:00

    参考までに、原文は以下のページのようです。
    http://www.techrepublic.com/blog/tech-decision-maker/hiring-a-programmer-ask-these-questions-in-the-interview/
    > Explain the difference between “equality” and “equivalence”
    と記述があります。

    キャンセル

  • 2015/09/10 12:07

    なるほど、元記事が英語なのですね。
    その日本語訳だけを読んでいるから、なんだかナンセンスな内容が多く見えてしまうのかもしれませんね。
    ありがとうございます。

    キャンセル

+1

「等値 = 等価 = 同値」 国語的には同じ意味を持ちます。
Javaの場合、等値演算子(==)を「等価比較」という呼び方で表し始めると混乱が起きると思います。

質問者さんのおっしゃるように、「同一か否か」については判定が特別な場合(実体を特定する時)に限られるので意味的に全く異なりますが、前述の表現は「同じ値かどうか」もしくは「同じ値である」ことを表すので、文脈的によって若干ですが異なります。

ただ異なっても、求めるところが「等価値」ということには変わりありません。

こんなQ&Aがあるのですが、英語(identity, equality)で捉える癖を付けた方が混乱は少ないかもしれません。


似て非なる言語「JavaScript」には、等値演算子(==)と同値演算子(===)という表現があるので、もしかするとそのせいで余計に日本語が混乱している可能性もあります…

どちらにしても、最終的にプログラム的に必要なことがどちらなのか理解することが一番大切だと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/09 17:16

    あ、でも僕の考え方もすでに言葉が混乱していますね。
    書いてみて気が付いてしまいました…失礼しました。

    キャンセル

  • 2015/09/10 09:04

    pikovoltさん
    回答ありがとうございます。
    意外とこの等値、等価は理解が難しいところですね。
    確かに等値演算子、同値演算子があるので余計混乱しています。
    丁寧な回答ありがとうございました。

    キャンセル

+1

"=="で比較する場合,数値(プリミティブ型)であろうと参照型であろうと同じ挙動をするのではないかと私は考えています.
プリミティブ値の場合は「値そのもの」がメモリ上に入ります.参照型はその実体が置かれている「場所を示す数値」が入っています.
"=="はすなわちこの値同士を比較し(数値同士で型が違えば適切な型に変換して)等しいかどうかを判定しているのだと思います.参照型なら同じ数値を指す=同じものを指している,と捉えて判定します.これで「同じ」」ならば,物自体が同じなので「同一」です.
一方,「論理的に比較」する場合は,この「格納した場所」は問題ではなく,その「指し示す先の実体の内容」に注目します.例え物が違ってもその中身が同じならば「同じ」と判定します.中身の値が同じかどうかを判定するので「同値」です.

例えるならばプリントの類がわかりやすいでしょうか.同じ内容を印刷したプリントを2枚持ってきた場合,この2枚のプリントは物として違うので「同一」ではないですが,書いてある内容は同じ(書いてある内容が一字一句同じである)なので「同値」です.
等値=同一,等価=同値の対応はややこしいですね.大方別の人物が違う日本語をあてて混在したのではないでしょうか・・・.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/10 10:25

    swordoneさん
    回答ありがとうございます。

    そうなんですね。
    だとしたら意味合いとしては

    等値=同一
    等価=同値

    という解釈でなんとなく合っているんですね。

    ==演算子かequalsメソッドによる判定かどうかは置いといて。
    同一、同値はそれでも区別できますが。

    ただ等値、等価という日本語自体が英語を訳したものであり、JavaScriptとかで使う等値演算子、同値演算子と混在したりしてややこしくなっているといった感じでしょうか。

    なんとなくわかってきました。

    「論理的に比較」の意味がわからなかったので、その解釈があって助かりました。


    そもそもこの質問を投稿したのも
    「プログラマーの力量を見極める--面接官になったら尋ねるべき質問実例集」
    http://japan.zdnet.com/sp/10things/20409456/
    を見て尋ねました。

    少しこの質問はどうなのかなあと思ってしまうところではあります。
    同値・同一の意味合いで聞いているのなら、同値・同一で聞けばいいし。。

    後半はただの個人的感想になってしまいました。

    回答ありがとうございました。感謝しています。

    キャンセル

+1

たとえば次の値の比較をどう言うか。

int i = 1;
double d = 1.0;

ここで、 i と d は「等値ではない」が、「等価である」と言いたい。
両者を == で比較してみる。

System.out.println( i == d ); // true


true が返る。

これはあたりまえではない。 
いわゆる暗黙の型変換というやつで、int 型 の i を「等価な」 double 値に変換した上で d との等値性を評価している。

では次はどうか。

float f = 0.1f;
double d2 = 0.1;
System.out.println( f == d2 ); // false

これも、f と d は等値ではないが、等価であると言いたい。

しかし結果は false になる。
f も「等価な」 double に暗黙的に変換されるが、その結果は等値にならない。

Java の == 演算子はあくまで値のメモリ(やレジスタ)上のビットパターンが完全に一致することを判定する。
これをここではとりあえず等値と呼ぶことにしたい。
暗黙の型変換はそれとは別の話で、コンパイラが空気を読んでサービスでやってくれていることなので、納得いかなくても文句は言えない。

System.out.println( f == (float)d2 ); // true
System.out.println( 1 == (int)1.99999 ); // true
System.out.println( 1 == '1' ); // false
System.out.println( 49 == '1' ); // true


1 と 1.0 が等しくあってほしいのは、人間の頭の中であって、コンパイラはできるだけそれに沿った評価をするよう実装されている。
そうすると、もう一方の「等価である」とは何と何を「等しいとみなすか」という、仕様(決め)の問題であるということになる。

オブジェクトのequals()でもう少し考えてみよう。

Java API のドキュメントをみると Object#equals() をみると、equivalence と「同値」、 equal を「等価な」と訳していて微妙だ。

System.out.println( "java" == "JAVA" ); // false
System.out.println( "java" == "java" ); // true
System.out.println( "java" == new String("java") ); // false
System.out.println( "java".equals(new String("java")) ); // true
System.out.println( "java".equalsIgnoreCase("JAVA") ); // true

ArrayList<String> al =  new ArrayList<>(Arrays.asList("a", "b", "c"));
LinkedList<String> ll = new LinkedList<>(al);
LinkedHashSet<String> set = new LinkedHashSet<>(ll);
System.out.println( al.equals(ll) ); // true
System.out.println( al.equals(set) ); // false

Java の場合 オブジェクトを == で比較するとき、参照値(アドレス)の等値性を見ているのであって、それは「同一」インスタンスかどうかを判定しているにすぎない。オブジェクトについて等値か等価かという区別とは別の話だ。

オブジェクトが等値であるとは、そのメンバとさらにそのメンバを全てたどって、最末端のプリミティブ型データを == で比較して全て一致した場合の事を言うのだろう。しかしそれは現実的ではない。

かと言って、どこで妥協すればいいのか、オブジェクトが等しいかどうかの定義は一概には決められない。 Java ではその判定基準はクラスの equals() 実装に任される。
つまり、Java の equals() は常に等価性で評価するとみなされる。
オブジェクトの内実データが全く異なっていても、あるいはクラス(型)が異なっていても equals() が true を返せばそれらは区別されない。

これが自分なりの理解だけれども、あえて前のコメントの定義に合わせて、「等値」は内部表現(値)の比較であり、「等価」はルール(論理)による比較といってみても、あながちずれてはいないかもしれない。

JavaScript, Ruby, PHP など一部の言語は等値と等価を区別した比較演算子を持っているが、呼び名は一致しない。
C++ は演算子そのものをオーバーライドできて、== でさえプログラマが再定義できるので、等値性は保証されない。

1 == "1";   // true
1 === "1";  // false 

言語以外にも、
Windows のファイル名は大文字と小文字の違いを区別しないので等価だ。
MacOS のファイル名は等値性で区別するので、徹底的に正規化され濁点さえも分離される。
SQL Server はデフォルトで片仮名と平仮名、半角と全角を等価であるとみなし区別しない。

まあ、概念の違いはいい、納得してもらったとしよう。

問題は、面接官のいう「等値」と「等価」という言葉に、上記のような(あるいは別の)意味合いで使い分けされている前提があるのか、ということだけれども、現状、ご存知のとおり混乱している。
技術用語として「等値」と「等価」の区別が重要で厳密に定義されていてその知識が問われているなら、どこか資格試験の教科書にでもしっかり書いてあるはずで、それこそググれば正解がすぐに出てくるはずだ。

そうでないなら、質問のための質問であって、そんなに真に受けることでもないのだと思う。

さて、元ネタの元ネタの equality と equivalence の違いというのは、おそらくスコット・メイヤーズのEffective STL という本にある連想コンテナに関連した議論を踏まえている。
↓のあたりで一部英語で読める。
https://books.google.co.jp/books?id=7x2MxvbjGsYC&pg=PT756&dq=effective+C%2B%2B+equality+equivalence&hl=ja&sa=X&ved=0ahUKEwjSqcneuZ_NAhXFJJQKHZHBD94Q6AEILDAA#v=onepage&q=effective%20C%2B%2B%20equality%20equivalence&f=false
今手元にはないけれども、その日本語版では 等値性(equality) と 等価性(equivalence)に訳されていたと思う。

スコット・メイヤーズの Effective C++ を始めとする Effective シリーズは一時期プログラマのバイブル的な必読書で、今のおっさんが若い頃必死こいて勉強したものだ。うがった見方をすれば、面接官の質問の本来の趣旨は、それぐらい読んでないわけないよな、という単なるおっさんのイヤミぐらいなのかもしれない。

ちなみに最初に参照されたブログでの解答例はどれもピント外れなのであまり参考にしない方がいいです。

長文失礼

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.77%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る