我在程序中导入了数学库,我试图通过以下方式找到最少三个数字:
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)
Run Code Online (Sandbox Code Playgroud)
但是,当我运行我的程序时,我收到以下错误:
./levenshtein_distance.go:36: cannot use int(v0[j + 1] + 1) (type int) as type float64 in argument to math.Min
Run Code Online (Sandbox Code Playgroud)
我觉得这很奇怪,因为我写了另一个程序
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)))
Run Code Online (Sandbox Code Playgroud)
通过这种方法,我收到以下错误:
./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
Run Code Online (Sandbox Code Playgroud)
所以为了摆脱这个问题,我只是把结果归还给了 int
我认为这是非常低效和难以阅读:
v1[j+1] = int(math.Min(float64(v1[j]+1), math.Min(float64(v0[j+1]+1), float64(v0[j]+cost))))
Run Code Online (Sandbox Code Playgroud)
我还写了一个小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)]
}
Run Code Online (Sandbox Code Playgroud)
two*_*two 47
不,我认为写这样的东西很好:例如,stdlib的sort.go靠近文件的顶部:
func min(a, b int) int {
if a < b {
return a
}
return b
}
Run Code Online (Sandbox Code Playgroud)
你的math.Min(2, 3)
工作是因为Go中的数字常量是无类型的.除了避免不必要的转换之外,最好不要对整数使用浮点函数,因为不是每个2^53
都有精确的math.Min(2, 3)
表示(特别是2 ^ 53以上的那些).
Von*_*onC 13
在问题 59488之后 ,Go 1.21(2023 年第 3 季度)将包含两个新的内置命令,如CL 498495所示:
\n// The max built-in function returns the largest value of a fixed number of\n// arguments of [cmp.Ordered] types. There must be at least one argument.\nfunc max[T cmp.Ordered](x T, y ...T) T\n// The min built-in function returns the smallest value of a fixed number of\n// arguments of [cmp.Ordered] types. There must be at least one argument.\nfunc min[T cmp.Ordered](x T, y ...T) T\n
Run Code Online (Sandbox Code Playgroud)\n\n\n\n最小值和最大值
\n内置函数
\nmin
和max
分别计算固定数量的有序类型参数的最小\xe2\x80\x94 或最大\xe2\x80\x94 值。
\n必须至少有一个参数。与运算符相同的类型规则适用:
\n\n
\n- 对于有序参数
\nx
和y
,min(x, y)
如果x + y
有效,则有效,并且 的类型min(x, y)
是 的类型x + y
(对于 max 也类似)。- 如果所有参数都是常数,则结果也是常数。
\nRun Code Online (Sandbox Code Playgroud)\nvar x, y int\nm := min(x) // m == x\nm := min(x, y) // m is the smaller of x and y\nm := max(x, y, 10) // m is the larger of x and y but at least 10\nc := max(1, 2.0, 10) // c == 10.0 (floating-point kind)\nf := max(0, float32(x)) // type of f is float32\nvar s []string\n_ = min(s...) // invalid: slice arguments are not permitted\nt := max("", "foo", "bar") // t == "foo" (string kind)\n
对于数字参数,min 和 max 是可交换的和结合的:
\nRun Code Online (Sandbox Code Playgroud)\nmin(x, y) == min(y, x)\nmin(x, y, z) == min(min(x, y), z) == min(x, min(y, z))\n
没有用于整数的内置min或max函数,但是编写自己的函数很简单。由于支持可变参数函数,我们甚至可以通过一次调用来比较更多整数:
func MinOf(vars ...int) int {
min := vars[0]
for _, i := range vars {
if min > i {
min = i
}
}
return min
}
Run Code Online (Sandbox Code Playgroud)
用法:
MinOf(3, 9, 6, 2)
Run Code Online (Sandbox Code Playgroud)
同样,这里是max函数:
func MaxOf(vars ...int) int {
max := vars[0]
for _, i := range vars {
if max < i {
max = i
}
}
return max
}
Run Code Online (Sandbox Code Playgroud)
例如,
package main
import "fmt"
func min(x, y int) int {
if x < y {
return x
}
return y
}
func main() {
t := "stackoverflow"
v0 := make([]int, len(t)+1)
v1 := make([]int, len(t)+1)
cost := 1
j := 0
v1[j+1] = min(v1[j]+1, min(v0[j+1]+1, v0[j]+cost))
fmt.Println(v1[j+1])
}
Run Code Online (Sandbox Code Playgroud)
输出:
1