You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现结合元素特征与燃油占比的动态权重计算通用函数?

问题描述

需要实现一个根据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")
}
问题根源
  1. 权重逻辑与需求反向:TransferFee和Distance都是越小越优的指标,但当前权重计算是直接将两者与权重占比相乘后相加,数值越大权重越高,完全违背“选费用更低/距离更短”的需求。
  2. 排序规则错误:代码按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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 02:02:11