我在我的程序中导入了数学库,我试图通过以下方式找到三个数字中的最小值:
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 许可协议
在 Go 1.18 之前,一次性函数是标准方法;例如, stdlib 的 sort.go 在文件顶部附近执行:
您可能仍然想要或需要使用这种方法,以便您的代码适用于 1.18 以下的 Go 版本!
从 Go 1.18 开始,您可以编写一个 通用的
min
函数,它在运行时与手动编码的单一类型版本一样高效,但适用于任何类型<
和>
运营商:已经 讨论 过更新 stdlib 以添加现有函数的通用版本,但如果发生这种情况,则要等到更高版本。
math.Min(2, 3)
碰巧可以工作,因为 Go 中的数字常量是无类型的。但是,请注意通常将 float64 视为通用数字类型,因为2^53
以上的整数如果转换为 float64 将被四舍五入。