浮动型的映射键

问题描述 投票:-1回答:1

我有一个这样的结构类型。

type Vertex struct {
    X, Y, Z float32
}

我想创建一个键为 Vertex 型。

var vertices map[Vertex]struct{}

问题是 Go 会尝试将float32与 ==!= 哪些 适用于float32。相反,我更喜欢用一个近似于 epsilon.

我研究过 此职位但我不知道如何实现它,因为我的密钥 struct 有3个字段。谁能帮我用我的结构体作为映射键?谢谢,我有一个这样的结构类型:type Vertex struct { X, Y, Z float32 }。

go
1个回答
0
投票

想法

受@ShubhamSrivastava评论的启发,我们的想法是:1、将坐标四舍五入到特定的小数点。

  • float32 坐标会被四舍五入到一个特定的小数点上

理由

由于确切的 ==!= (map key要求的)比较对于float来说是不合适的,当 float32 是四舍五入到有限的小数点。

实施

我把我的float32字段在 Vertex 类型,通过这些方法将其转换为 小数点:

// 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
}
© www.soinside.com 2019 - 2024. All rights reserved.