Javaで開発をしています。
等値と等価の違いについて知りたいと思っています。
等値=同一
等価=同値
ということなのかなあと思っているのですが、合っているでしょうか?
そもそも
同一は、インスタンスが同じこと。==演算子で判定する。
同値とは、インスタンスは違うけれど、値が同じこと。equalsメソッドで判定する。
だと思っています。
調べてみたのですが、個人的な意見を述べているサイトが多く、いまいち自信が持てません。
字面的には組み合わせも逆のような気がするし、調べていくうちにまったくの別物のような気もしてきました。。
有識者の方々よろしくお願いします。
追記
このサイトを拝見しました。
http://ryo021021.hatenablog.com/entry/2014/01/02/134232
変数で考えます。等値はそのまま、その変数が持っている値が等しいことです。つまり、以下の式です。[==]を"等価演算子"なんて呼ぶために混乱します。
if (a == b) printf("等値\n");
等価は、昇順にソートする場合等でいう以下の式です。
if (!(a < b) && !(b < a)) printf("等価\n");
値を、それ自体で比較するのか、論理的に比較するのか、といった感じでしょうか。
私の認識は違っていたかもしれません。
等価の「論理的に比較する」の意味がいまいちよくわかりません。
もしアドバイスいただける方がいらっしゃればお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答5件
0
・等値判定(==)はメモリ内の値が等しいかを判断します。
・等価判定(Object#equals)はインスタンスが等しいかを判定します。
int型はプリミティブなのでObjectを継承していません。そのため、メモリ上の値を等しいかどうかに使います。
対してオブジェクトは内部にたくさんの属性を持っています。そのため、Object型を継承しているクラスはインスタンスの比較基準(どの属性が一致していたら同じかなど)をObject#equalsをオーバーライドして決定することが義務付けられています。
オブジェクトが等価かどうかをオブジェクトの特性などから論理的に判断する行為を「論理的に比較する」と表現しているのではないでしょうか。
投稿2015/09/09 07:59
編集2015/09/09 08:02総合スコア18155
0
ベストアンサー
間違っていないか不安ですが、自分なりの考えで回答してみます。
例えば、二人の人物を比較するとします。
これを人間(=Humanクラス)として比較するならば、(哲学的には諸説ありそうですが)その「価値が等しい」ことの定義は「全く同じ人物である」ことに他なりません。つまり、Humanクラスにおいて等価の意味は「等値であること」になります。
java
1class Human { 2 public boolean equals(Object obj) { 3 return this == obj; 4 } 5}
走者(=Runnerクラス)として比較するならば、その「価値が等しい」ことの定義は走る速さとスタミナで決まるかもしれません。加えて言えば、相手も走者である必要があります。
java
1class Runner extends Human { 2 protected int speed; 3 protected int stamina; 4 public boolean equals(Object obj) { 5 if (obj instanceof Runner) { 6 runner = (Runner)obj; 7 return this.speed == runner.speed && this.stamina == runner.stamina; 8 } else { 9 return false; 10 } 11 } 12}
短距離走者(=Sprinterクラス)として比較するならばもはやスタミナは問題にならず、その価値はスピードだけで決まるかもしれませんね。比較自体は走者であればだれとでも出来そうです。
java
1class Sprinter extends Runner { 2 public boolean equals(Object obj) { 3 if (obj instanceof Runner) { 4 runner = (Runner)obj; 5 return this.speed == runner.speed; 6 } else { 7 return false; 8 } 9 } 10}
このように二つの物の価値を比べる時に、その評価基準は「それが何であるか」によって変わります。一方で「等しい値である」ことの定義はいつでも同じです。
等値と等価の違いはそこにあるのではないでしょうか。
投稿2015/09/10 01:24
総合スコア594
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/09/10 02:31 編集
2015/09/10 02:30
2015/09/10 02:39 編集
2015/09/10 02:42 編集
2015/09/10 02:52
2015/09/10 03:00
2015/09/10 03:07
0
たとえば次の値の比較をどう言うか。
java
1int i = 1; 2double d = 1.0;
ここで、 i と d は「等値ではない」が、「等価である」と言いたい。
両者を == で比較してみる。
java
1System.out.println( i == d ); // true
true が返る。
これはあたりまえではない。
いわゆる暗黙の型変換というやつで、int 型 の i を「等価な」 double 値に変換した上で d との等値性を評価している。
では次はどうか。
java
1float f = 0.1f; 2double d2 = 0.1; 3System.out.println( f == d2 ); // false
これも、f と d は等値ではないが、等価であると言いたい。
しかし結果は false になる。
f も「等価な」 double に暗黙的に変換されるが、その結果は等値にならない。
Java の == 演算子はあくまで値のメモリ(やレジスタ)上のビットパターンが完全に一致することを判定する。
これをここではとりあえず等値と呼ぶことにしたい。
暗黙の型変換はそれとは別の話で、コンパイラが空気を読んでサービスでやってくれていることなので、納得いかなくても文句は言えない。
java
1System.out.println( f == (float)d2 ); // true 2System.out.println( 1 == (int)1.99999 ); // true 3System.out.println( 1 == '1' ); // false 4System.out.println( 49 == '1' ); // true 5
1 と 1.0 が等しくあってほしいのは、人間の頭の中であって、コンパイラはできるだけそれに沿った評価をするよう実装されている。
そうすると、もう一方の「等価である」とは何と何を「等しいとみなすか」という、仕様(決め)の問題であるということになる。
オブジェクトのequals()でもう少し考えてみよう。
Java API のドキュメントをみると Object#equals() をみると、equivalence と「同値」、 equal を「等価な」と訳していて微妙だ。
java
1System.out.println( "java" == "JAVA" ); // false 2System.out.println( "java" == "java" ); // true 3System.out.println( "java" == new String("java") ); // false 4System.out.println( "java".equals(new String("java")) ); // true 5System.out.println( "java".equalsIgnoreCase("JAVA") ); // true 6 7ArrayList<String> al = new ArrayList<>(Arrays.asList("a", "b", "c")); 8LinkedList<String> ll = new LinkedList<>(al); 9LinkedHashSet<String> set = new LinkedHashSet<>(ll); 10System.out.println( al.equals(ll) ); // true 11System.out.println( al.equals(set) ); // false
Java の場合 オブジェクトを == で比較するとき、参照値(アドレス)の等値性を見ているのであって、それは「同一」インスタンスかどうかを判定しているにすぎない。オブジェクトについて等値か等価かという区別とは別の話だ。
オブジェクトが等値であるとは、そのメンバとさらにそのメンバを全てたどって、最末端のプリミティブ型データを == で比較して全て一致した場合の事を言うのだろう。しかしそれは現実的ではない。
かと言って、どこで妥協すればいいのか、オブジェクトが等しいかどうかの定義は一概には決められない。 Java ではその判定基準はクラスの equals() 実装に任される。
つまり、Java の equals() は常に等価性で評価するとみなされる。
オブジェクトの内実データが全く異なっていても、あるいはクラス(型)が異なっていても equals() が true を返せばそれらは区別されない。
これが自分なりの理解だけれども、あえて前のコメントの定義に合わせて、「等値」は内部表現(値)の比較であり、「等価」はルール(論理)による比較といってみても、あながちずれてはいないかもしれない。
JavaScript, Ruby, PHP など一部の言語は等値と等価を区別した比較演算子を持っているが、呼び名は一致しない。
C++ は演算子そのものをオーバーライドできて、== でさえプログラマが再定義できるので、等値性は保証されない。
JavaScript
11 == "1"; // true 21 === "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 シリーズは一時期プログラマのバイブル的な必読書で、今のおっさんが若い頃必死こいて勉強したものだ。うがった見方をすれば、面接官の質問の本来の趣旨は、それぐらい読んでないわけないよな、という単なるおっさんのイヤミぐらいなのかもしれない。
ちなみに最初に参照されたブログでの解答例はどれもピント外れなのであまり参考にしない方がいいです。
長文失礼
投稿2016/06/11 11:26
総合スコア12
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
"=="で比較する場合,数値(プリミティブ型)であろうと参照型であろうと同じ挙動をするのではないかと私は考えています.
プリミティブ値の場合は「値そのもの」がメモリ上に入ります.参照型はその実体が置かれている「場所を示す数値」が入っています.
"=="はすなわちこの値同士を比較し(数値同士で型が違えば適切な型に変換して)等しいかどうかを判定しているのだと思います.参照型なら同じ数値を指す=同じものを指している,と捉えて判定します.これで「同じ」」ならば,物自体が同じなので「同一」です.
一方,「論理的に比較」する場合は,この「格納した場所」は問題ではなく,その「指し示す先の実体の内容」に注目します.例え物が違ってもその中身が同じならば「同じ」と判定します.中身の値が同じかどうかを判定するので「同値」です.
例えるならばプリントの類がわかりやすいでしょうか.同じ内容を印刷したプリントを2枚持ってきた場合,この2枚のプリントは物として違うので「同一」ではないですが,書いてある内容は同じ(書いてある内容が一字一句同じである)なので「同値」です.
等値=同一,等価=同値の対応はややこしいですね.大方別の人物が違う日本語をあてて混在したのではないでしょうか・・・.
投稿2015/09/10 00:59
総合スコア20651
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/09/10 01:25
0
「等値 = 等価 = 同値」 国語的には同じ意味を持ちます。
Javaの場合、等値演算子(==)を「等価比較」という呼び方で表し始めると混乱が起きると思います。
質問者さんのおっしゃるように、「同一か否か」については判定が特別な場合(実体を特定する時)に限られるので意味的に全く異なりますが、前述の表現は「同じ値かどうか」もしくは「同じ値である」ことを表すので、文脈的によって若干ですが異なります。
ただ異なっても、求めるところが「等価値」ということには変わりありません。
こんなQ&Aがあるのですが、英語(identity, equality)で捉える癖を付けた方が混乱は少ないかもしれません。
似て非なる言語「JavaScript」には、等値演算子(==)と同値演算子(===)という表現があるので、もしかするとそのせいで余計に日本語が混乱している可能性もあります…
どちらにしても、最終的にプログラム的に必要なことがどちらなのか理解することが一番大切だと思います。
投稿2015/09/09 08:15
退会済みユーザー
総合スコア0
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/09/09 08:09 編集
2015/09/09 08:26
2015/09/10 00:54 編集
2015/09/10 00:50
2015/09/10 01:10
2015/09/10 03:12 編集