From: Nobuyoshi Nakada Date: 2009-07-25T13:05:12+09:00 Subject: [ruby-dev:38897] Re: Rational#hash なかだです。 At Wed, 22 Jul 2009 20:52:46 +0900, Tadayoshi Funaba wrote in [ruby-dev:38850]: > いつだったか、rational などの hash が変ったようですが、意味が解っていな > いんですが、みてみると、 変更の理由は[ruby-dev:37777]の後半にあるように、hash値の衝突が多 いという問題のためです。 At Fri, 16 Jan 2009 20:00:08 +0900, Keiju ISHITSUKA wrote in [ruby-dev:37777]: > けいじゅ@いしつかです. (snip) > 例えば, Complexだと > > @real.hash ^ @imag.hash > > となっています. 実際には, これはあまり良くなくて, @real==@image のとき > つねに同じ値になってしまいます. そこで, 別のseedを与え > > @real.hash(seed1) ^ @image.hash(seed2) > > の様にすると, 上記の問題はなくなります. これは, Array等のhash関数でも > 同様です. また, Fixnum#hashとObject#hashも別のseedを与えるのもよさそう > な気がします. > h[0] = rb_hash(rb_obj_class(self)); > n = rb_hash(dat->num); > h[1] = NUM2LONG(n); > n = rb_hash(dat->den); > h[2] = NUM2LONG(n); > > rb_hash を都合3回呼んでいて、後の2回は NUM2LONG していて、最初のはそう > じゃないんですが、これはこういうものということでいいんですか。 たしかに、Bignumが返されるとhash値が変わってしまってまずいので最 初もNUM2LONG()すべきでしょうが、Arrayなど他のクラスではサブクラ スでも同じhash値になるようになっているので、最初のrb_hash() を除 くほうがいいと思います。 Index: complex.c =================================================================== --- complex.c (revision 24266) +++ complex.c (working copy) @@ -1157,13 +1157,12 @@ static VALUE nucomp_hash(VALUE self) { - long v, h[3]; + long v, h[2]; VALUE n; get_dat1(self); - h[0] = rb_hash(rb_obj_class(self)); n = rb_hash(dat->real); - h[1] = NUM2LONG(n); + h[0] = NUM2LONG(n); n = rb_hash(dat->imag); - h[2] = NUM2LONG(n); + h[1] = NUM2LONG(n); v = rb_memhash(h, sizeof(h)); return LONG2FIX(v); Index: rational.c =================================================================== --- rational.c (revision 24266) +++ rational.c (working copy) @@ -1361,13 +1361,12 @@ static VALUE nurat_hash(VALUE self) { - long v, h[3]; + long v, h[2]; VALUE n; get_dat1(self); - h[0] = rb_hash(rb_obj_class(self)); n = rb_hash(dat->num); - h[1] = NUM2LONG(n); + h[0] = NUM2LONG(n); n = rb_hash(dat->den); - h[2] = NUM2LONG(n); + h[1] = NUM2LONG(n); v = rb_memhash(h, sizeof(h)); return LONG2FIX(v); -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦