Я начну с небольшого обобщения и предоставлю один метод для обработки обоих случаев.
def excel_quartile(array, quartile)
# Returns nil if array is empty and covers the case of array.length == 1
return array.first if array.length <= 1
sorted = array.sort
# The 4th quartile is always the last element in the sorted list.
return sorted.last if quartile == 4
# Source: http://mathworld.wolfram.com/Quartile.html
quartile_position = 0.25 * (quartile*sorted.length + 4 - quartile)
quartile_int = quartile_position.to_i
lower = sorted[quartile_int - 1]
upper = sorted[quartile_int]
lower + (upper - lower) * (quartile_position - quartile_int)
end
Тогда вы можете сделать удобные методы:
def excel_lower_quartile(array)
excel_quartile(array, 1)
end
def excel_upper_quartile(array)
excel_quartile(array, 3)
end
Примечание: метод excel_quartile
соответствует ожиданиям для quartile in { 1, 2, 3, 4}
. Всё остальное гарантирую провал.
Обновление:
Формула, которую я использовал, прямо не приводится на цитируемом мной веб-сайте, но это абстракция для метода Фрейнда и Перлеса для расчета квартильной позиции.
Дальнейшее обновление:
В исходном коде есть ошибка, хотя вы никогда не должны сталкиваться с ней: u - u.trunc
всегда находится в интервале [0.0, 1.0), таким образом, единственное время, которое будет напоминать целое число, - это когда u - u.trunc = 0
. Тем не менее, (u - u.trunc)
все еще является экземпляром Float, когда u
является Float, поэтому ваш код никогда не встречается при просчитанном индексе. Кстати, если бы u - u.trunc было целым числом, ваш метод вернул бы последний элемент массива.