Une implémentation Levenshtein en C # et F #. La version C # est 10 fois plus rapide pour deux chaînes d'environ 1500 caractères. C #: 69 ms, F # 867 ms. Pourquoi? Autant que je sache, ils font exactement la même chose? Peu importe qu'il s'agisse d'une version Release ou Debug.
EDIT: Si quelqu'un vient ici pour rechercher spécifiquement l'implémentation Edit Distance, elle est cassée. Le code de travail est ici .
C # :
private static int min3(int a, int b, int c)
{
return Math.Min(Math.Min(a, b), c);
}
public static int EditDistance(string m, string n)
{
var d1 = new int[n.Length];
for (int x = 0; x < d1.Length; x++) d1[x] = x;
var d0 = new int[n.Length];
for(int i = 1; i < m.Length; i++)
{
d0[0] = i;
var ui = m[i];
for (int j = 1; j < n.Length; j++ )
{
d0[j] = 1 + min3(d1[j], d0[j - 1], d1[j - 1] + (ui == n[j] ? -1 : 0));
}
Array.Copy(d0, d1, d1.Length);
}
return d0[n.Length - 1];
}
F # :
let min3(a, b, c) = min a (min b c)
let levenshtein (m:string) (n:string) =
let d1 = Array.init n.Length id
let d0 = Array.create n.Length 0
for i=1 to m.Length-1 do
d0.[0] <- i
let ui = m.[i]
for j=1 to n.Length-1 do
d0.[j] <- 1 + min3(d1.[j], d0.[j-1], d1.[j-1] + if ui = n.[j] then -1 else 0)
Array.blit d0 0 d1 0 n.Length
d0.[n.Length-1]
c#
performance
f#
inline
Robert Jeppesen
la source
la source
Réponses:
Le problème est que la
min3
fonction est compilée comme une fonction générique qui utilise une comparaison générique (je pensais que cela utilise justeIComparable
, mais c'est en fait plus compliqué - cela utiliserait une comparaison structurelle pour les types F # et c'est une logique assez complexe).Dans la version C #, la fonction n'est pas générique (elle prend juste
int
). Vous pouvez améliorer la version F # en ajoutant des annotations de type (pour obtenir la même chose qu'en C #):... ou en faisant
min3
commeinline
(dans ce cas, il sera spécialiséint
lors de son utilisation):Pour une chaîne aléatoire
str
de longueur 300, j'obtiens les nombres suivants:la source
inline
fonctionne comme un modèle C ++, qui se spécialiserait enint
fonction du site d'appel.inline
. La raison pour laquelle le comportement par défaut est différent est qu'il s'appuie sur des génériques .Net qui sont gérés par le runtime (et, sans doute, ne sont pas si bons pour écrire du code numérique générique). Cependant, l'utilisation du comportement C ++ dans F # entraînerait un gonflement du code, car F # utilise beaucoup plus les génériques.