囲碁で2つの整数の間の最小値を求める正しい方法は何ですか?
質問
プログラムでmathライブラリをインポートし、以下のような方法で3つの数値の最小値を求めようとしています。
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行目を再現するためのプログラムを以下に示します。 パッケージ 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)]
}
どのように解決するのですか?
いや、そういう書き方でいいと思うんですよ、例えば。 はstdlibのsort.goが はファイルの先頭付近でそれを行います。
func min(a, b int) int {
if a < b {
return a
}
return b
}
math.Min(2, 3)
が動作するようになったのは
の数値定数は型付けされていないためです。
. しかし、float64 を一般的な数値型として扱うことには注意が必要です、なぜなら
の上の整数は
2^53
は float64 に変換されると丸められます。
.
しかし
は安定した Go では動作しませんが
には、これを書いている時点では
Go 1.18 ベータ
を書くことができます。
ジェネリック
min
機能
であり、ハンドコーディングされた単一型バージョンと同じように実行時に効率的です。
これまでにも 議論 を更新して既存の関数のジェネリックバージョンを追加するという議論がありましたが、もしそうなったとしても、それは後のバージョンになるまでないでしょう。
関連
-
[解決済み] Goでenumを表現する慣用的な方法は何ですか?
-
[解決済み] Goでオブジェクトの型を見つけるには?
-
[解決済み] GOPATHとGOROOTの値はどうすればよいですか?
-
[解決済み] 2枚のスライスの等価性を確認する
-
[解決済み】Goのタグはどのような用途に使われますか?
-
[解決済み】Goで空の文字列をテストする最良の方法は何ですか?
-
[解決済み】空のスライスを初期化する正しい方法
-
[解決済み] reflectを使用して、構造体フィールドの値を設定するにはどうすればよいですか?
-
[解決済み] GoLangで文字列を比較するにはどうしたらいいですか?
-
[解決済み] ソースツリー全体に対するgo fmt
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] GoのToString()関数
-
[解決済み] 現在時刻に時・分・秒を足す
-
[解決済み] テキストファイルを文字列配列に読み込む(そして書き込む)
-
[解決済み] bytes.Buffer does not implement io.Writer" というエラーメッセージが表示される。
-
[解決済み] チャネルバッファサイズとは何ですか?
-
[解決済み] go get で「インポートパスが認識されない」。
-
[解決済み] Golangパッケージとは別の名前で実行ファイルをビルドする方法
-
[解決済み] Golang で構造体をマップに変換する関数
-
[解決済み] RWMutexの使い方は?
-
Golangを使用してディレクトリのすべてのコンテンツを削除するには?