Files
2026-08-11 00:10:12 +08:00

40 lines
1.1 KiB
Python

from __future__ import annotations
from typing import Iterable
def percentile(values: Iterable[float], percent: float) -> float | None:
ordered = sorted(float(value) for value in values)
if not ordered:
return None
if len(ordered) == 1:
return ordered[0]
rank = (len(ordered) - 1) * (percent / 100.0)
lower = int(rank)
upper = min(lower + 1, len(ordered) - 1)
weight = rank - lower
return ordered[lower] * (1.0 - weight) + ordered[upper] * weight
def summarize(values: Iterable[float]) -> dict[str, float | int | None]:
ordered = sorted(float(value) for value in values)
if not ordered:
return {
"count": 0,
"min": None,
"max": None,
"median": None,
"p50": None,
"p90": None,
"p95": None,
}
return {
"count": len(ordered),
"min": ordered[0],
"max": ordered[-1],
"median": percentile(ordered, 50),
"p50": percentile(ordered, 50),
"p90": percentile(ordered, 90),
"p95": percentile(ordered, 95),
}