Мой код основан на методах, описанных здесь и здесь .
def fraction?(number)
number - number.truncate
end
def percentile(param_array, percentage)
another_array = param_array.to_a.sort
r = percentage.to_f * (param_array.size.to_f - 1) + 1
if r <= 1 then return another_array[0]
elsif r >= another_array.size then return another_array[another_array.size - 1]
end
ir = r.truncate
another_array[ir] + fraction?((another_array[ir].to_f - another_array[ir - 1].to_f).abs)
end
Пример использования:
test_array = [95.1772, 95.1567, 95.1937, 95.1959, 95.1442, 95.061, 95.1591, 95.1195,
95.1065, 95.0925, 95.199, 95.1682]
test_values = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
test_values.each do |value|
puts value.to_s + ": " + percentile(test_array, value).to_s
end
Выход:
0.0: 95.061
0.1: 95.1205
0.2: 95.1325
0.3: 95.1689
0.4: 95.1692
0.5: 95.1615
0.6: 95.1773
0.7: 95.1862
0.8: 95.2102
0.9: 95.1981
1.0: 95.199
Проблема здесь в том, что 80-й процентиль выше, чем 90-й и 100-й. Однако, насколько я могу судить, моя реализация такая, как описано, и она возвращает правильный ответ для приведенного примера (0.9).
Есть ли в моем коде ошибка, которую я не вижу? Или есть лучший способ сделать это?