Сообщения ObjC, которые отправляются в ноль и чьи возвращаемые значения имеют размер, больше, чем sizeof (пусто*) производят неопределенные значения на процессорах PowerPC. В дополнение к этому эти сообщения заставляют неопределенные значения быть возвращенными в областях структур, размер которых больше, чем 8 байтов на процессорах Intel также. Vincent Gable описал это приятно в его сообщение в блоге
Попробуйте следующее:
arr = [5, 6, 7, 8]
arr.inject{ |sum, el| sum + el }.to_f / arr.size
=> 6.5
Обратите внимание на .to_f
, который вам понадобится, чтобы избежать проблем с целочисленным делением. Вы также можете:
arr = [5, 6, 7, 8]
arr.inject(0.0) { |sum, el| sum + el } / arr.size
=> 6.5
Вы можете определить его как часть Array
, как предложил другой комментатор, но вам нужно избегать целочисленного деления, иначе ваши результаты будут неправильными. Кроме того, это обычно не применимо ко всем возможным типам элементов (очевидно, среднее значение имеет смысл только для вещей, которые можно усреднить). Но если вы хотите пойти по этому пути, используйте следующее:
class Array
def sum
inject(0.0) { |result, el| result + el }
end
def mean
sum / size
end
end
Если вы раньше не видели inject
, это не так волшебно, как может показаться. Он выполняет итерацию по каждому элементу, а затем применяет к нему значение аккумулятора. Затем аккумулятор передается следующему элементу. В этом случае наш аккумулятор представляет собой просто целое число, которое отражает сумму всех предыдущих элементов.
Редактировать: Комментатор Дэйв Рэй предложил хорошее улучшение.
Редактировать: Предложение комментатора Гленна Джекмана, используя arr.inject (: +). To_f
, тоже неплохо, но, возможно, слишком умно, если вы не знаете, что происходит. : +
- это символ; при передаче в inject он применяет метод, названный символом (в данном случае операция сложения), к каждому элементу по значению аккумулятора.
Редактировать: Комментатор Дэйв Рэй предложил хорошее улучшение.
Редактировать: Предложение комментатора Гленна Джекмана, используя arr .inject (: +). to_f
тоже хорош, но, возможно, слишком умен, если вы не знаете, что происходит. : +
- это символ; когда передается на inject, он применяет метод, названный символом (в данном случае операция сложения), к каждому элементу по значению аккумулятора.
Редактировать: Комментатор Дэйв Рэй предложил хорошее улучшение.
Редактировать: Предложение комментатора Гленна Джекмана, используя arr .inject (: +). to_f
тоже хорош, но, возможно, слишком умен, если вы не знаете, что происходит. : +
является символом; при передаче в inject он применяет метод, названный символом (в данном случае операция сложения), к каждому элементу по значению аккумулятора.
a = [0,4,8,2,5,0,2,6]
sum = 0
a.each { |b| sum += b }
average = sum / a.length
На этом компьютере нет ruby, но что-то в этой степени должно работа:
values = [0,4,8,2,5,0,2,6]
total = 0.0
values.each do |val|
total += val
end
average = total/values.size
class Array
def sum
inject( nil ) { |sum,x| sum ? sum+x : x }
end
def mean
sum.to_f / size.to_f
end
end
[0,4,8,2,5,0,2,6].mean
a = [0,4,8,2,5,0,2,6]
a.instance_eval { reduce(:+) / size.to_f } #=> 3.375
Версия, которая не использует instance_eval
, будет:
a = [0,4,8,2,5,0,2,6]
a.reduce(:+) / a.size.to_f #=> 3.375