本方案依据 GB 10765-2021 中 33 项营养素的最小值、最大值,对实测值 kjhl 进行连续评分。
设计目标:
0~100;N.S.(无上限)项目;| 符号 | 含义 |
|---|---|
L |
最小值 |
U |
最大值 |
x |
实测值 kjhl |
W |
区间宽,W = U - L |
t |
归一化位置,t = (x - L) / W |
base |
边界基础分,默认 60 |
p |
区间内曲线形状参数,默认 2 |
k |
超范围下降速度,默认 8 |
m |
无上限项目接近满分速度,默认 2 |
适用于 U 存在且 U > L 的项目。
条件:
L ≤ x ≤ U
计算:
W = U - L
t = (x - L) / W
score = base + (100 - base) × [1 - (2 × |t - 0.5|)^p]
默认参数:
base = 60
p = 2
得分特点:
| 位置 | t |
得分 |
|---|---|---|
| 区间中心 | 0.5 |
100 |
| 区间边界 | 0 或 1 |
60 |
| 越靠近中心 | — | 得分越高 |
| 越靠近边界 | — | 得分越低 |
| 变化方式 | — | 连续,无跳变 |
条件:
x < L
计算:
W = U - L
d = (L - x) / W
score = max(0, base × exp(-k × d))
默认参数:
base = 60
k = 8
条件:
x > U
计算:
W = U - L
d = (x - U) / W
score = max(0, base × exp(-k × d))
默认参数:
base = 60
k = 8
适用于 U = None 或 N.S. 的项目,例如 α-亚麻酸。
条件:
x < L
计算:
d = (L - x) / L
score = max(0, base × exp(-k × d))
默认参数:
base = 60
k = 8
条件:
x ≥ L
计算:
score = base + (100 - base) × [1 - exp(-m × (x - L) / L)]
默认参数:
base = 60
m = 2
得分特点:
60;100;不同营养素重要性不同,建议按类别设置权重。
| 序号 | 类别 | 权重 |
|---|---|---|
| 1 | 蛋白质、脂肪、碳水化合物 | 3.0 |
| 2 | 亚油酸、α-亚麻酸 | 2.0 |
| 3 | 维生素类 | 2.0~2.5 |
| 4 | 矿物质类 | 2.0~2.5 |
| 5 | 胆碱、肌醇、牛磺酸 | 1.0~1.5 |
| 6 | 33 项以外可选营养素 | 0.5,附加分封顶 |
示例权重表:
| 序号 | 营养素 | 权重 |
|---|---|---|
| 1 | 蛋白质 | 3.0 |
| 2 | 脂肪 | 3.0 |
| 3 | 碳水化合物 | 3.0 |
| 4 | 亚油酸 | 2.0 |
| 5 | α-亚麻酸 | 2.0 |
| 6 | 维生素A | 2.5 |
| 7 | 维生素D | 2.5 |
| 8 | 维生素E | 2.0 |
| 9 | 维生素K1 | 2.0 |
| 10 | 维生素B1 | 2.0 |
| 11 | 维生素B2 | 2.0 |
| 12 | 维生素B6 | 2.0 |
| 13 | 维生素B12 | 2.0 |
| 14 | 烟酸 | 2.0 |
| 15 | 叶酸 | 2.0 |
| 16 | 泛酸 | 2.0 |
| 17 | 维生素C | 2.0 |
| 18 | 生物素 | 2.0 |
| 19 | 胆碱 | 1.5 |
| 20 | 钠 | 2.0 |
| 21 | 钾 | 2.0 |
| 22 | 铜 | 2.0 |
| 23 | 镁 | 2.0 |
| 24 | 铁 | 2.5 |
| 25 | 锌 | 2.5 |
| 26 | 锰 | 2.0 |
| 27 | 钙 | 2.5 |
| 28 | 磷 | 2.0 |
| 29 | 碘 | 2.5 |
| 30 | 氯 | 2.0 |
| 31 | 硒 | 2.5 |
| 32 | 肌醇 | 1.0 |
| 33 | 牛磺酸 | 1.0 |
单项得分是每个营养素根据实测值,用连续打分函数算出的原始分数。
范围:
0 ~ 100
它回答:
这个营养素本身表现得好不好?
加权得分是在单项得分基础上,乘以该营养素的权重。
公式:
加权得分 = 单项得分 × 权重
它回答:
这个营养素对最终总分的实际贡献有多大?
| 对比项 | 单项得分 | 加权得分 |
|---|---|---|
| 含义 | 这一项自己得了多少分 | 这一项对总分贡献了多少 |
| 公式 | score |
score × weight |
| 范围 | 0~100 | 例如 0~300 |
| 是否考虑权重 | 不考虑 | 考虑 |
| 用途 | 看单项好坏 | 算总分 |
| 是否最终结果 | 不是 | 也不是,还要除以权重总和 |
单项得分记为 score_i,权重记为 weight_i。
最终总分:
总分 = Σ(score_i × weight_i) / Σ(weight_i)
说明:
0~100;33 项以外营养素作为附加分处理。
规则建议:
0~1 分;+5 分;示例:
bonus = min(5, Σ(extra_score_j))
最终总分可表示为:
最终总分 = 基础加权总分 + bonus
如果希望总分不超过 100,可以:
最终总分 = min(100, 基础加权总分 + bonus)
每项明细建议输出:
| 序号 | 营养素 | 单位 | 最小值 | 最大值 | 实测值 | 单项得分 | 权重 | 加权得分 |
|---|---|---|---|---|---|---|---|---|
| 1 | 蛋白质 | g | 0.43 | 0.72 | 0.55 | 92.35 | 3.0 | 277.05 |
| 2 | 脂肪 | g | 1.05 | 1.43 | 1.20 | 95.12 | 3.0 | 285.36 |
| … | … | … | … | … | … | … | … | … |
最后输出:
加权总分:XX.XX
| 参数 | 默认值 | 作用 |
|---|---|---|
base |
60 |
边界基础分 |
p |
2 |
区间内曲线形状 |
k |
8 |
超范围下降速度 |
m |
2 |
无上限项目接近满分速度 |
参数调整建议:
| 目标 | 调整 |
|---|---|
| 边界更严格 | 降低 base,提高 k |
| 中间更宽松 | 提高 p |
| 超范围扣得更狠 | 提高 k |
| 无上限项目更快接近满分 | 提高 m |
输入:L、U、x
│
├─ U 存在吗?
│ │
│ ├─ 是
│ │ ├─ L ≤ x ≤ U ?
│ │ │ ├─ 是:t = (x-L)/W
│ │ │ │ score = base + (100-base)×[1-(2×|t-0.5|)^p]
│ │ │ └─ 否:d = 超出比例
│ │ │ score = base × exp(-k×d)
│ │ │
│ └─ 否(N.S.)
│ ├─ x < L :d = (L-x)/L
│ │ score = base × exp(-k×d)
│ └─ x ≥ L :score = base + (100-base)×[1-exp(-m×(x-L)/L)]
│
└─ 输出:score,范围 0~100
import math
def score_normal(x, L, U, base=60.0, p=2.0, k=8.0):
"""
有上下限的营养素连续打分。
x: 实测值
L: 最小值
U: 最大值
base: 边界基础分
p: 区间内曲线形状参数
k: 超范围下降速度
返回 0~100 的分数
"""
if U is None or U <= L:
raise ValueError("U 必须大于 L")
W = U - L
if L <= x <= U:
t = (x - L) / W
score = base + (100 - base) * (1 - (2 * abs(t - 0.5)) ** p)
return max(0.0, min(100.0, score))
else:
if x < L:
d = (L - x) / W
else:
d = (x - U) / W
score = base * math.exp(-k * d)
return max(0.0, min(100.0, score))
def score_no_upper(x, L, base=60.0, k=8.0, m=2.0):
"""
只有下限、没有上限的营养素连续打分。
x: 实测值
L: 最小值
base: 下限处基础分
k: 低于下限时下降速度
m: 高于下限时接近满分的速度
"""
if x < L:
d = (L - x) / L
score = base * math.exp(-k * d)
return max(0.0, min(100.0, score))
else:
score = base + (100 - base) * (1 - math.exp(-m * (x - L) / L))
return max(0.0, min(100.0, score))
def score_one(x, L, U):
"""
根据实测值、上下限,返回单项得分。
"""
if U is None:
return score_no_upper(x, L)
else:
return score_normal(x, L, U)
按 GB 10765-2021 的 33 项营养素,用连续函数打分:区间内以中心最高、边界 60 分,公式为
base + (100-base)×[1-(2×|t-0.5|)^p];超范围用base×exp(-k×d)快速下降;无上限项目单独处理;单项0~100分,按权重加权汇总为总分。