"""统计计算工具""" import math from typing import List def _percentile_at(sorted_data: list[float], pct: float) -> float: """在线性插值下,返回排序后数据的指定百分位值。 注意:调用方必须确保 data 已排序。 """ n = len(sorted_data) if n == 0: return 0.0 k = (pct / 100.0) * (n - 1) f = math.floor(k) c = math.ceil(k) if f == c: return sorted_data[int(k)] d0 = sorted_data[int(f)] * (c - k) d1 = sorted_data[int(c)] * (k - f) return d0 + d1 def percentile(data: List[float], pct: float) -> float: """计算指定百分位数的值(线性插值) 空数据返回 0.0,调用方应通过检查 count 来判断是否有数据。 """ return _percentile_at(sorted(data), pct) def percentiles(data: List[float], pcts: List[float]) -> dict: """单次排序,批量计算多个百分位,返回 {pct: value}。""" sorted_data = sorted(data) return {p: _percentile_at(sorted_data, p) for p in pcts} def mean(data: List[float]) -> float: """算术平均值""" if not data: return 0.0 return sum(data) / len(data) def std(data: List[float]) -> float: """样本标准差(n-1)""" if len(data) < 2: return 0.0 m = mean(data) variance = sum((x - m) ** 2 for x in data) / (len(data) - 1) return math.sqrt(variance) def min_val(data: List[float]) -> float: """最小值""" return min(data) if data else 0.0 def max_val(data: List[float]) -> float: """最大值""" return max(data) if data else 0.0