在 Go 中找到两个整数之间最小值的正确方法是什么?

新手上路,请多包涵

我在我的程序中导入了数学库,我试图通过以下方式找到三个数字中的最小值:

v1[j+1] = math.Min(v1[j]+1, math.Min(v0[j+1]+1, v0[j]+cost))

其中 v1 声明为:

 t := "stackoverflow"
v1 := make([]int, len(t)+1)

但是,当我运行我的程序时,出现以下错误:

 ./levenshtein_distance.go:36: cannot use int(v0[j + 1] + 1) (type int) as type float64 in argument to math.Min

我觉得这很奇怪,因为我有另一个我写的程序

fmt.Println(math.Min(2,3))

并且该程序输出 2 没有抱怨。

所以我最终将这些值转换为 float64,这样 math.Min 就可以工作了:

 v1[j+1] = math.Min(float64(v1[j]+1), math.Min(float64(v0[j+1]+1), float64(v0[j]+cost)))

使用这种方法,我收到以下错误:

 ./levenshtein_distance.go:36: cannot use math.Min(int(v1[j] + 1), math.Min(int(v0[j + 1] + 1), int(v0[j] + cost))) (type float64) as type int in assignment

所以为了解决这个问题,我只是将结果转换回 int

我认为这是非常低效且难以阅读的:

 v1[j+1] = int(math.Min(float64(v1[j]+1), math.Min(float64(v0[j+1]+1), float64(v0[j]+cost))))

我还写了一个小的 minInt 函数,但我认为这应该是不必要的,因为其他使用 math.Min 的程序在取整数时工作得很好,所以我认为这必须是我的程序的问题,而不是图书馆本身的问题。

我做错了什么吗?

这是一个可用于重现上述问题的程序,特别是第 36 行:package main

 import (
    "math"
)

func main() {
    LevenshteinDistance("stackoverflow", "stackexchange")
}

func LevenshteinDistance(s string, t string) int {
    if s == t {
        return 0
    }
    if len(s) == 0 {
        return len(t)
    }
    if len(t) == 0 {
        return len(s)
    }

    v0 := make([]int, len(t)+1)
    v1 := make([]int, len(t)+1)

    for i := 0; i < len(v0); i++ {
        v0[i] = i
    }

    for i := 0; i < len(s); i++ {
        v1[0] = i + 1
        for j := 0; j < len(t); j++ {
            cost := 0
            if s[i] != t[j] {
                cost = 1
            }
            v1[j+1] = int(math.Min(float64(v1[j]+1), math.Min(float64(v0[j+1]+1), float64(v0[j]+cost))))
        }

        for j := 0; j < len(v0); j++ {
            v0[j] = v1[j]
        }
    }
    return v1[len(t)]
}

原文由 ILikeTacos 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 972
2 个回答

在 Go 1.18 之前,一次性函数是标准方法;例如, stdlib 的 sort.go 在文件顶部附近执行:

 func min(a, b int) int {
    if a < b {
        return a
    }
    return b
}

您可能仍然想要或需要使用这种方法,以便您的代码适用于 1.18 以下的 Go 版本!

从 Go 1.18 开始,您可以编写一个 通用的 min 函数,它在运行时与手动编码的单一类型版本一样高效,但适用于任何类型 <> 运营商:

 func min[T constraints.Ordered](a, b T) T {
    if a < b {
        return a
    }
    return b
}

func main() {
    fmt.Println(min(1, 2))
    fmt.Println(min(1.5, 2.5))
    fmt.Println(min("Hello", "世界"))
}

已经 讨论 过更新 stdlib 以添加现有函数的通用版本,但如果发生这种情况,则要等到更高版本。

math.Min(2, 3) 碰巧可以工作,因为 Go 中的数字常量是无类型的。但是,请注意通常将 float64 视为通用数字类型,因为 2^53 以上的整数如果转换为 float64 将被四舍五入

原文由 twotwotwo 发布,翻译遵循 CC BY-SA 4.0 许可协议

整数没有内置的 min 或 max 函数,但是编写自己的函数很简单。多亏了对可变参数函数的支持,我们甚至可以通过一次调用来比较更多的整数:

 func MinOf(vars ...int) int {
    min := vars[0]

    for _, i := range vars {
        if min > i {
            min = i
        }
    }

    return min
}

用法:

 MinOf(3, 9, 6, 2)

同样,这里是 max 函数:

 func MaxOf(vars ...int) int {
    max := vars[0]

    for _, i := range vars {
        if max < i {
            max = i
        }
    }

    return max
}

原文由 Sergiu Sandrean 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题