go - float 类型的 map 键

标签 go

我有这样的结构类型:

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/

    相关文章:

    ruby - Rust 数学错误

    types - 迭代一个接口(interface)

    go - 如何从goroutine的channel持续接收数据

    arrays - 如何在 Go 中创建自定义类型元素的自定义类型数组?

    go - 如何在 Go 中中止 net.Dial 调用?

    xml - 如何在go中将2个xml标记解析为1个结构?

    http - 中间件如何在 Go 的 chi 路由中工作以及 http.Handler 参数在中间件中指的是什么?

    reflection - golang 获取类型的 reflect.Type

    google-app-engine - 如何为 Google App Engine Go 开发设置 IntelliJ IDEA?

    去反射(reflect)通过结构标签找到