对数标度 - PHP排名

时间:2015-12-23 13:14:17

标签: php algorithm sorting math

我目前正在构建一个需要根据内部操作/分数进行排名的系统。分数本身可以在0到20000之间的任何地方。

我需要我创建的功能来对用户进行排名,以返回介于1-100之间的值。如果这是不可能的,那么将100以上的任何结果集返回为100就可以了。我目前在确保创建用于确定分数的对数算法时遇到困难。

我尝试过以下功能:

echo 1 + sqrt(500 + 2000 * $score) / 50;

但是,对于较低的值,此返回的结果变化不足,而对于较高的值,该结果的指数增加。

比例低/平均结束时的输入分数示例为:

  • 0.15
  • 1
  • 7
  • 12

比例高端的示例输入

  • 236.4
  • 1211
  • 17899.70

非常感谢任何帮助。现在已经坚持了几天。上面的函数是我迄今为止的最佳尝试,但是建议低/中结果之间没有足够的差异,而较高/结果之间的差异太大。

谢谢,

丹尼尔

3 个答案:

答案 0 :(得分:4)

这是一个开放式的问题,并且没有明确的答案有不同的权衡。我不是一个PHP程序员,但是类似下面的东西应该有效。

# THESE PARAMETERS CONTROL THE RANKING ALGORITHM.
$rescale = 0;
$spread = 1;

function rescore ($n) {
    return log($n) + $rescale;
}

function rank ($scores) {
    return 100 / (1 + exp(- $spread * array_sum(array_map("rescore", $scores))));
}

您应该选择$rescale,以便将平均分数重新调整为接近0的值。并使用$spread进行游戏,直到您对分数的分散程度感到满意为止。

这个想法是log将大范围的分数转换为可比较范围内的数字,可以是正数也可以是负数。添加一堆重新分数,你会获得一个任意实数。然后将其转换为逻辑函数(详见https://en.wikipedia.org/wiki/Logistic_function),将其转换为所需范围内的数字。

答案 1 :(得分:1)

尝试密切关注Wikepedia中的定义,其中" [对数]刻度上的每个标记都是前一个标记乘以一个值,"我们设置value^100 = 20000并到达value = 1.104104805。然后可以使用类似于以下的函数来实现这种对数标度吗?

function rank($score){
  return log($score,1.104104805);
}

输出:

$scores = [0.15,1,7,12,236.4,1211,17899.70];

foreach ($scores as $score){
  echo "Score: " . $score . ", Rank: " . rank($score) . "\n";
}

/*
Score: 0.15, Rank: -19.156079885479
Score: 1, Rank: 0
Score: 7, Rank: 19.648736275112
Score: 12, Rank: 25.091228109202
Score: 236.4, Rank: 55.187884698844
Score: 1211, Rank: 71.683855953272
Score: 17899.7, Rank: 98.879704658993
*/

答案 2 :(得分:1)

感谢您的帮助。这是我最终得到的结果(感谢Jake L Price的帮助)

在初始问题之后得分略有不同(120,000是比例的最高端),但算法的逻辑需要保持不变。如下所示,我们使用log * 10来获得可理解的低数字。然后我们再将这个乘以一个数字,确保120,000的最高等级为100。

    echo $this->rank($score);

    public function rank($score)
        {
            //-- log reg time
            // 7.143963378055477 being the numberic multiplier to ensure 120,000 has the score of 100.
            $res = 7.143963378055477 * log($score * 10);
            return $res;
        }

现在正在返回

$scores = [0.15,1,7,12,236.4,1211,17899.70, 120000];

    foreach ($scores as $score){
        echo "Score: " . $score . ", Rank: " . $this->rank($score) . "</br>";
    }

输出:

Score: 0.15, Rank: 2.896627883404
Score: 1, Rank: 16.449583579206
Score: 7, Rank: 30.351094421044
Score: 12, Rank: 34.201665683178
Score: 236.4, Rank: 55.495096060882
Score: 1211, Rank: 67.166020848577
Score: 17899.7, Rank: 86.407125230156
Score: 120000, Rank: 100