一尘不染

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

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)]
}

阅读 134

收藏
2021-12-24

共1个答案

一尘不染

不,我认为写这样的东西很好:例如,stdlib 的 sort.go在文件顶部附近执行它:

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

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

尽管我编写本文时它不适用于稳定的 Go,但在Go 1.18 beta 中,您可以编写一个通用min函数,该函数在运行时与手动编码的单一类型版本一样高效。

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

2021-12-24