├── README.md ├── cosine.go └── cosine_test.go /README.md: -------------------------------------------------------------------------------- 1 | # Cosine similarity in Go (Golang) 2 | Return the similarity (float64) of 2 []float64 3 | -------------------------------------------------------------------------------- /cosine.go: -------------------------------------------------------------------------------- 1 | package cosine_similarity 2 | 3 | import ( 4 | "errors" 5 | "math" 6 | ) 7 | 8 | func Cosine(a []float64, b []float64) (cosine float64, err error) { 9 | count := 0 10 | length_a := len(a) 11 | length_b := len(b) 12 | if length_a > length_b { 13 | count = length_a 14 | } else { 15 | count = length_b 16 | } 17 | sumA := 0.0 18 | s1 := 0.0 19 | s2 := 0.0 20 | for k := 0; k < count; k++ { 21 | if k >= length_a { 22 | s2 += math.Pow(b[k], 2) 23 | continue 24 | } 25 | if k >= length_b { 26 | s1 += math.Pow(a[k], 2) 27 | continue 28 | } 29 | sumA += a[k] * b[k] 30 | s1 += math.Pow(a[k], 2) 31 | s2 += math.Pow(b[k], 2) 32 | } 33 | if s1 == 0 || s2 == 0 { 34 | return 0.0, errors.New("Vectors should not be null (all zeros)") 35 | } 36 | return sumA / (math.Sqrt(s1) * math.Sqrt(s2)), nil 37 | } 38 | -------------------------------------------------------------------------------- /cosine_test.go: -------------------------------------------------------------------------------- 1 | package cosine_similarity 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestCosine(t *testing.T) { 8 | 9 | a := []float64{1, 1, 0, 0, 1} 10 | b := []float64{1, 1, 0, 0, 1} 11 | cos, err := Cosine(a, b) 12 | if err != nil { 13 | t.Error(err) 14 | } 15 | if cos < 0.99 { 16 | t.Error("Expected similarity of 1, got instead ", cos) 17 | } 18 | a = []float64{0, 1, 0, 1, 1} 19 | b = []float64{1, 0, 1, 0, 0} 20 | cos, err = Cosine(a, b) 21 | if err != nil { 22 | t.Error(err) 23 | } 24 | if cos != 0 { 25 | t.Error("Expected similarity of 0, got instead ", cos) 26 | } 27 | a = []float64{1, 1, 0} 28 | b = []float64{1, 0, 1} 29 | cos, err = Cosine(a, b) 30 | if err != nil { 31 | t.Error(err) 32 | } 33 | if cos < 0.49999 || cos > 0.5 { 34 | t.Error("Expected similarity of 0.5, got instead ", cos) 35 | } 36 | a = []float64{0, 1, 1, 1, 0} 37 | b = []float64{1, 0} 38 | cos, err = Cosine(a, b) 39 | if err != nil { 40 | t.Error(err) 41 | } 42 | if cos != 0 { 43 | t.Error("Expected similarity of 0, got instead ", cos) 44 | } 45 | } 46 | --------------------------------------------------------------------------------