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

PHP中如何基于百分位区间数组匹配总分对应的百分位值

PHP高效实现百分位匹配方案

由于你的percentile_bounds数组本身是升序排列的,不需要全量遍历过滤,可以直接用二分查找实现O(logn)时间复杂度的匹配,比原实现的O(n)性能提升明显,同时天然兼容所有边界条件:

<?php

// 升序数组中查找第一个大于等于目标值的索引
function binary_search_first_ge(array $arr, int $target): int {
    $left = 0;
    $right = count($arr);
    while ($left < $right) {
        $mid = (int)(($left + $right) / 2);
        if ($arr[$mid] >= $target) {
            $right = $mid;
        } else {
            $left = $mid + 1;
        }
    }
    return $left;
}

// 测试用例
$percentile_bounds = [84, 104, 109, 115, 120, 123, 125, 127, 129, 132, 135, 136, 137,139, 141, 145, 148, 151, 155, 159];
$percentiles = [0,  5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95];

// 示例1:130 => 40
$total_score = 130;
$index = binary_search_first_ge($percentile_bounds, $total_score);
echo $percentiles[$index == 0 ? 0 : $index - 1] . PHP_EOL;

// 示例2:153 =>85
$total_score = 153;
$index = binary_search_first_ge($percentile_bounds, $total_score);
echo $percentiles[$index == 0 ? 0 : $index - 1] . PHP_EOL;

// 示例3:100 =>0
$total_score = 100;
$index = binary_search_first_ge($percentile_bounds, $total_score);
echo $percentiles[$index == 0 ? 0 : $index - 1] . PHP_EOL;

// 示例4:120 =>15
$total_score = 120;
$index = binary_search_first_ge($percentile_bounds, $total_score);
echo $percentiles[$index == 0 ? 0 : $index - 1] . PHP_EOL;

// 边界测试:84 =>0
$total_score = 84;
$index = binary_search_first_ge($percentile_bounds, $total_score);
echo $percentiles[$index == 0 ? 0 : $index - 1] . PHP_EOL;

// 边界测试:70 =>0
$total_score = 70;
$index = binary_search_first_ge($percentile_bounds, $total_score);
echo $percentiles[$index == 0 ? 0 : $index - 1] . PHP_EOL;

// 边界测试:160(超过最大值)=>95
$total_score = 160;
$index = binary_search_first_ge($percentile_bounds, $total_score);
echo $percentiles[$index == 0 ? 0 : $index - 1] . PHP_EOL;

短数组场景简洁写法

如果你的百分位区间数组长度很小,想要更精简的代码,也可以用逆序遍历提前终止的方案,比原实现少一次array_search遍历:

<?php
$percentile_bounds = [84, 104, 109, 115, 120, 123, 125, 127, 129, 132, 135, 136, 137,139, 141, 145, 148, 151, 155, 159];
$percentiles = [0,  5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95];
$total_score = 120;

$res = 0;
foreach (array_reverse($percentile_bounds, true) as $k => $v) {
    if ($v < $total_score) {
        $res = $percentiles[$k];
        break;
    }
}
echo $res;

内容的提问来源于stack exchange,提问作者My Work

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 01:45:03