英文:
Is NaN a comparable type in golang?
问题
我遇到了一个使用NaN作为映射键的golang测验,它运行时没有任何错误。如果映射的键应该是可比较的,那么NaN是可比较类型吗?还是这是一个编译器错误,允许NaN作为键。
这是测验源代码,go playground链接和下面的代码。
package main
var x = 0.0
func main() {
var a = x / x // a = NaN
var m = map[float64]int{a: 1}
m[a] = 2
for k := range m {
delete(m, k)
}
println(len(m)) // 输出 2
}
英文:
I came across a golang quiz which used NaN as a maps key and it ran without any error. If map's keys are supposed to be comparable is NaN a comparable type or is this a compiler bug which allowed NaN as a key.
Here's the quiz source, the go playground link and code below.
package main
var x = 0.0
func main() {
var a = x / x // a = NaN
var m = map[float64]int{a: 1}
m[a] = 2
for k := range m {
delete(m, k)
}
println(len(m)) // prints 2
}
答案1
得分: 3
任何float64类型的值都是可比较的。比较任意两个浮点数没有问题。你可以将NaN与3.141或NaN与NaN进行比较。
问题不在于NaN/浮点数的可比较性。问题在于无论是将NaN与任何其他值比较,还是将NaN与自身比较,结果都将为false。
对于所有的x,包括NaN本身,都有NaN != x。
这使得将NaN用作映射键基本上是不可能的,因为无法找到一个NaN。
英文:
Any float64 is comparable. There is no problem comparing any two floats. You can compare a NaN to 3.141 or NaN to NaN.
The problem is not comparability of NaNs/floats. The problem is that any comparison of a NaN with anything, even an other NaN or itself will result in false.
NaN != x for all x, including NaN
This makes using NaNs as map keys basically impossible because it's impossible to find a NaN.
答案2
得分: 1
简短回答是这不是一个编译器的错误。
映射需要可比较的类型作为键。浮点数(无论是float32还是float64)是可比较的类型。关于NaN(以及以不同方式的零,可以是正零或负零),奇怪的是,虽然你可以比较两个NaN,但它们总是被认为是不相等的。所以当x
是NaN时,某个浮点数值x
不等于它自己。这会产生一些意外情况。
问题20660的评论指出在许多其他语言中也存在类似的问题。
英文:
The short answer is that this is not a compiler bug.
Maps require comparable types as keys. Float (regardless of float32 or float64) is a comparable type. What's odd about NaN (and in a different way, zero, which can be either positive or negative zero) is that while you can compare two NaNs, they always compare as unequal. So some float value x
is not equal to itself when x
is NaN. This produces surprises.
Issue 20660 comments note that the same kind of problems occur in a number of other languages.
I particularly like Russ Cox's comment that there are only bad answers here.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论