我有这样的结构类型:
type Vertex struct {
X, Y, Z float32
}
我打算用
Vertex
类型的键创建一个 map :var vertices map[Vertex]struct{}
问题是
Go
会尝试将float32与不适合float32的==
和!=
进行比较。相反,我更喜欢与epsilon
进行近似比较。我已经研究了this post,但是我不知道如何实现它,因为我的关键
struct
有3个字段。有人可以帮助我将我的结构用作 map 键吗?谢谢。
最佳答案
理念
受到@ShubhamSrivastava评论的启发,想法是:
float32
坐标将四舍五入到特定的小数点基本原理
由于精确的
==
和!=
比较(由映射键要求)不适合进行浮点运算,因此当float32
始终四舍五入到小数点后,这种比较更有意义。实作
我通过以下方法将
Vertex
类型内的float32字段四舍五入为特定的小数点:// round floating point fields of my type to a specific decimal point
func vertRoundTo(vi Vertex, decimals uint32) (vo Vertex, err error) {
if vo.X, err = roundTo(vi.X, decimals); err != nil {
return Vertex{}, err
}
if vo.Y, err = roundTo(vi.Y, decimals); err != nil {
return Vertex{}, err
}
if vo.Z, err = roundTo(vi.Z, decimals); err != nil {
return Vertex{}, err
}
return
}
// round float32 to a specific decimal point
// https://stackoverflow.com/a/52048478/3405291
func roundTo(fi float32, decimals uint32) (fo float32, err error) {
if decimals < 1 {
err = errors.New("minimum decimal point is exceeded")
return
}
fo = float32(math.Round(float64(fi)*float64(decimals)) / float64(decimals))
return
}
我使用上面的方法是这样的:
// "cluster" is already filled with rounded floats
func (c *cluster) DoesClusterContainVertex(v Vertex) (does bool, err error) {
// coordinates would be rounded to a specific decimal point
// since exact == and != comparison is NOT proper for float
// such comparisons are required for map key
var vRound Vertex
if vRound, err = vertRoundTo(v, 4); err != nil {
return
}
if _, ok := c.verts[vRound]; ok {
// cluster contains vertex
does = true
}
return
}
关于go - float 类型的 map 键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62358008/