ハッシュのキーとして同一視されるものはなんであるか

http://blade.nagaokaut.ac.jp/cgi-bin/vframe.rb/ruby/ruby-list/47272?47272-47298+split-mode-vertical

# ruby
p({1 => true}[1.0]) #=> nil

あー。Pythonはそこのところゆるいよなぁ

# python
>>> {1: True}[1.0]
True
>>> {1: 1, 1.0: 1.0}
{1: 1.0}

Python浮動小数点数のhashを計算してみると面白い

>>> hash(1.0)
1
>>> hash(1.5)
1610645504
>>> hash(2.0)
2

ちょうど整数になる時だけハッシュ値が一致するようになっている。object.cの_Py_HashDouble(double v)で明確に「小数部が0の場合には整数と同じハッシュ値になるべきである」と書かれている。

if (fractpart == 0.0) {
    /* This must return the same hash as an equal int or long. */

この判断の根拠はここには書かれていない。

整数の1と浮動小数点の1.0のハッシュ値が一緒であって、かつハッシュのキーの一致性判定がisではなく==だからこうなるわけだが、僕としては気持ち悪く感じるなぁ。

>>> 1 == 1.0
True
>>> 1 is 1.0
False



Twitterから転載:

@sumim SmalltalkPythonと同じ。Dictionary new at: 1 put: true; at: 1.0 "=> true"

@kmizu これ http://bit.ly/9dFbOO Javaでも1.0と1はキーとして同一視されるな。