如何实现结合元素特征与燃油占比的动态权重计算通用函数?
问题描述
需要实现一个根据TransferFee(转移费用)和Distance(距离)计算元素权重的函数,需求如下:
- 当
FuelPercent(燃油占比)为95时,选中ID为2的对象,此时更低的转移费用优先级高于更短距离 - 当
FuelPercent为81时,选中ID为1的对象,此时更短距离优先级高于更低转移费用
但当前实现存在问题:无论设置何种权重占比,算法始终选中ID为1的元素,已知问题出在乘法运算环节,但不清楚具体修复方法。以下是Go语言实现代码:
package main import ( "encoding/json" "fmt" "sort" ) type PlanetInfo struct { ID int TransferFee float64 Distance float64 Weight float64 } func main() { fuelPercent := 95. engines := make([]PlanetInfo, 0) engines = append(engines, PlanetInfo{ ID: 1, TransferFee: 7.5, Distance: 96, }) engines = append(engines, PlanetInfo{ ID: 2, TransferFee: 6, Distance: 65, }) feeRatio := 0. distanceRatio := 0. switch { case fuelPercent > 90: feeRatio = 0.9 distanceRatio = 0.1 case fuelPercent >= 85 && fuelPercent < 90: feeRatio = 0.8 distanceRatio = 0.2 case fuelPercent >= 80 && fuelPercent < 85: feeRatio = 0.6 distanceRatio = 0.4 case fuelPercent < 80: feeRatio = 0.1 distanceRatio = 0.9 } fmt.Printf("distanceRatio: %f\n", distanceRatio) fmt.Printf("feeRation: %f\n", feeRatio) for i, r := range engines { fmt.Printf("%d; distanceRatio; %f * %f = %f\n", r.ID, r.Distance, distanceRatio, r.Distance*distanceRatio) fmt.Printf("%d; feeRation; %f * %f = %f\n", r.ID, r.TransferFee, feeRatio, r.TransferFee*feeRatio) fmt.Printf("%f * %f + %f + %f = %f\n", feeRatio, r.Distance, distanceRatio, r.TransferFee, feeRatio*r.TransferFee+distanceRatio*r.Distance) engines[i].Weight = r.TransferFee*feeRatio + r.Distance*distanceRatio } sort.Slice(engines, func(i, j int) bool { return engines[i].Weight > engines[j].Weight }) PrintStructJSON(engines) // always give first element } func PrintStructJSON(value interface{}) { result, err := json.MarshalIndent(value, "", "\t") if err != nil { fmt.Println(err) } fmt.Printf("\n" + string(result) + "\n") }
问题根源
- 权重逻辑与需求反向:
TransferFee和Distance都是越小越优的指标,但当前权重计算是直接将两者与权重占比相乘后相加,数值越大权重越高,完全违背“选费用更低/距离更短”的需求。 - 排序规则错误:代码按
Weight > Weight排序(权重高的在前),但由于权重计算逻辑反向,真正最优的对象权重反而更小,被排到了后面。
修复方案
核心是让权重逻辑与需求匹配,这里提供两种直观的修复方式:
方式1:修改排序规则(最简单)
保持当前权重计算方式,但排序时按权重从小到大排列——因为权重越小,代表TransferFee和Distance的加权和越小,越符合“费用低、距离短”的需求。
修复后的代码:
package main import ( "encoding/json" "fmt" "sort" ) type PlanetInfo struct { ID int TransferFee float64 Distance float64 Weight float64 } func main() { fuelPercent := 95. engines := make([]PlanetInfo, 0) engines = append(engines, PlanetInfo{ ID: 1, TransferFee: 7.5, Distance: 96, }) engines = append(engines, PlanetInfo{ ID: 2, TransferFee: 6, Distance: 65, }) feeRatio := 0. distanceRatio := 0. switch { case fuelPercent > 90: feeRatio = 0.9 distanceRatio = 0.1 case fuelPercent >= 85 && fuelPercent < 90: feeRatio = 0.8 distanceRatio = 0.2 case fuelPercent >= 80 && fuelPercent < 85: feeRatio = 0.6 distanceRatio = 0.4 case fuelPercent < 80: feeRatio = 0.1 distanceRatio = 0.9 } fmt.Printf("distanceRatio: %f\n", distanceRatio) fmt.Printf("feeRatio: %f\n", feeRatio) for i, r := range engines { weight := r.TransferFee*feeRatio + r.Distance*distanceRatio engines[i].Weight = weight fmt.Printf("ID %d: 权重 = %.2f*%.2f + %.2f*%.2f = %.2f\n", r.ID, r.TransferFee, feeRatio, r.Distance, distanceRatio, weight) } // 关键修改:按权重从小到大排序,权重小代表更优 sort.Slice(engines, func(i, j int) bool { return engines[i].Weight < engines[j].Weight }) PrintStructJSON(engines) } func PrintStructJSON(value interface{}) { result, err := json.MarshalIndent(value, "", "\t") if err != nil { fmt.Println(err) } fmt.Printf("\n" + string(result) + "\n") }
方式2:反转指标计算权重
将TransferFee和Distance转为“越大越优”的指标后再计算权重,比如用负数反转指标(避免0值问题)。示例代码如下:
// 替换权重计算部分 for i, r := range engines { // 用负数反转指标,让越小的费用/距离对应越大的权重值 weight := -r.TransferFee*feeRatio - r.Distance*distanceRatio engines[i].Weight = weight } // 保持原排序规则(权重高的在前) sort.Slice(engines, func(i, j int) bool { return engines[i].Weight > engines[j].Weight })
验证结果
- 当
fuelPercent=95时,ID2的权重为6*0.9 + 65*0.1 = 11.9,ID1的权重为7.5*0.9 + 96*0.1 = 16.35,排序后ID2在前,符合需求。 - 当
fuelPercent=81时,权重占比为feeRatio=0.6、distanceRatio=0.4,ID1权重为7.5*0.6 + 96*0.4 = 42.9,ID2权重为6*0.6 + 65*0.4 = 29.6(注:此处数据中ID2距离更短,若需求是选距离更短的对象,结果符合预期;若需求描述中ID1为更短距离,需检查数据是否正确)。
内容的提问来源于stack exchange,提问作者wisicoc
相关产品推荐
相关产品推荐

