package utils import ( "fmt" "math" "math/rand" "strconv" "strings" "sync" "time" "github.com/xrash/smetrics" ) func GetInvitation() string { var bs = make([]byte, 6) for i := 0; i < 6; i++ { rand.Seed(time.Now().UnixNano()) flag := rand.Intn(2) if flag == 1 { bs[i] = byte(rand.Float64()*10 + 48) } else { bs[i] = byte(rand.Float64()*26 + 65) } } return string(bs) } func GetInvitationLen(length int) string { var bs = make([]byte, length) for i := 0; i < length; i++ { rand.Seed(time.Now().UnixNano()) flag := rand.Intn(3) if flag == 1 { bs[i] = byte(rand.Float64()*10 + 48) } else if flag == 0 { bs[i] = byte(rand.Float64()*26 + 65) } else { bs[i] = byte(rand.Float64()*26 + 97) } } return string(bs) } func StringFloat64ToInt(s string) int { f1, err := strconv.ParseFloat(s, 64) if err != nil { return 0 } s1 := strconv.FormatFloat(math.Ceil(f1), 'f', -1, 64) i, _ := strconv.Atoi(s1) return i } // FindMostSimilarCode 使用协程并发地对比目标特征码与一组候选特征码, // 并找出相似度最高的特征码(若相似度高于阈值)及其相似度。 func FindMostSimilarCode(targetCode string, candidateCodes []string, similarityThreshold float64, boostThreshold float64, prefixSize int) (string, float64, bool) { var wg sync.WaitGroup maxSimilarity := 0.0 var closestCode string foundAboveThreshold := false resultChan := make(chan struct { similarity float64 code string }) for _, candidate := range candidateCodes { wg.Add(1) go func(candidate string) { defer wg.Done() similarity := smetrics.JaroWinkler(targetCode, candidate, boostThreshold, prefixSize) resultChan <- struct { similarity float64 code string }{similarity, candidate} }(candidate) } go func() { wg.Wait() close(resultChan) }() for result := range resultChan { if result.similarity > maxSimilarity { maxSimilarity = result.similarity closestCode = result.code if maxSimilarity >= similarityThreshold { foundAboveThreshold = true } } } return closestCode, maxSimilarity, foundAboveThreshold } // 计算余弦相似度 func CosineSimilarity(vec1Str, vec2Str string) float64 { vec1, _ := parseVectorFromString(vec1Str) vec2, _ := parseVectorFromString(vec2Str) dotProduct := 0.0 vec1Norm := 0.0 vec2Norm := 0.0 for i := range vec1 { dotProduct += vec1[i] * vec2[i] vec1Norm += vec1[i] * vec1[i] vec2Norm += vec2[i] * vec2[i] } if vec1Norm == 0 || vec2Norm == 0 { return 0 } return dotProduct / (math.Sqrt(vec1Norm) * math.Sqrt(vec2Norm)) } func parseVectorFromString(vecStr string) ([]float64, error) { vec := strings.Split(vecStr, ",") var parsedVec []float64 for _, strVal := range vec { floatVal, err := strconv.ParseFloat(strVal, 64) if err != nil { return nil, fmt.Errorf("failed to parse float value '%s': %w", strVal, err) } parsedVec = append(parsedVec, floatVal) } return parsedVec, nil } // float64转string的函数 func Float64ToString(input float64) string { return strconv.FormatFloat(input, 'f', -1, 64) }