以下のコードを実行すると何が出力されるでしょうか?
package main
import (
"fmt"
"math"
)
func main() {
a := map[float64]int{}
a[math.Acos(8)] = 1
a[math.Acos(8)] = 2
a[math.Acos(8)] = 3
i := 0
for range a {
i++
}
fmt.Println(i)
fmt.Println(len(a))
}
-
1
と1
-
1
と3
-
3
と1
-
3
と3
回答と解説
「4. 3
と 3
」が正解です。math.Acos(8)
の結果は NaN (Not a Number) です。 NaN
は特殊な浮動小数点の値で、どの値と ==
で比較しても、たとえ NaN 同士での比較でも、 false になります。 map のキーに NaN を指定すると、その値は過去に指定されたどのキーとも違う扱いになるので、毎度新しい値として代入されます。よって 3 回 NaN をキーにして値を代入した map は for-range ループは 3 回回りますし、 len
関数に対しても 3 を返します。よってどちらも 3
が表示されます。ちなみに、キーを NaN にした値は取り出せなくなります。たとえば一通り代入が終わったあとで v, ok := a[math.Acos(8)]
とやっても、 v
と ok
は 0
と false
になります。しかしながら蓄えた値は確かに存在していて、 len
関数の結果や fmt.Printf("%v\n", a)
の結果でわかります。それにも関わらず取り出せない、ブラックホールのような状態になっているわけです。