Работа с десятичными знаками в Ruby on Rails 3

Я пытаюсь рассчитать среднюю чистую цену продукта. У меня в модели продукта: total_sold и: total_net_revenue. Выполнение прямого деления в методе, как представляется, всегда приводит к 0. Я прибегал к использованию BigDecimal, поскольку я решил, что это проблема... но с моей последней итерацией кода ниже я все равно получаю ноль, когда ответ приходит к десятичное число.

def avg_price
  BigDecimal(total_sold.to_s) / (BigDecimal(total_net_revenue.to_s) / 100)
end  

Чистый доход - в центах, поэтому я делю на 100. Может кто-то указать, что я делаю неправильно или должен делать?

Ответ 1

total_net_revenue / total_sold

или

total_net_revenue / total_sold / 100.0

или

total_net_revenue.to_f / total_sold / 100

Эти три метода дают все большее количество точности, если вы этого хотите. Помните, что "средняя цена" - это "средняя цена/продажа". Это деньги за элемент, поэтому вы захотите сделать разделение в определенном порядке.

Ответ 2

Во-первых: Вы делите неправильный путь.

100 пунктов /150 долларов США =.667 единиц за доллар

против.

$150/100 items = $1.50 за элемент

Во-вторых: как и другие языки, вам нужно заставить одно из чисел в уравнении быть десятичным, чтобы результат был отлит как один. Поскольку ваш доход является целым числом, это означает, что все три значения были целыми числами, а это значит, что в результате вы получили целое число. Чтобы получить десятичное число, отбросьте один из них как число с плавающей запятой.

Другими словами, чтобы получить то, что вам нужно, сделайте следующее:

price_per_item = (total_net_revenue.to_f / 100) / total_sold

Ответ 3

То, что вы делаете, называется целочисленным делением, которое отбрасывает любой остаток, поскольку оно не будет выражаться в целых числах, например:

1 / 3 # == 0

Как отмечали другие респонденты, вы можете заставить деление с плавающей запятой. Вам нужно заставить первый аргумент быть float (1 здесь), вызвав .to_f. Второй аргумент автоматически будет принудительно введен в float, т.е.:

1.to_f / 3 # ~ 0.3333...

Обратите внимание, что как только вы переходите к номерам с плавающей запятой, результат, вообще говоря, уже не является точным. Вот почему я положил ~ 0.333.

Точные детали более востребованы. Я считаю, что в двоичной арифметике с плавающей запятой, которая распространена в сегодняшних микропроцессорах, полномочия 2 по-прежнему точны. Но целое число 3, например, больше не представлено точно, но только в пределах точности представления с плавающей запятой (обычно 1E-16 или около него для "двойной" точности).

Короче говоря, вот эмпирическое правило: если вы имеете дело с денежными ценностями, где важна точность (когда-либо было замечено несоответствие в расчете на 1 цент на счете за телефон?), не хранятся вычисленные результаты, t сохраняет значения в плавающих точках. Вместо этого используйте целочисленные или десятичные типы данных (которые внутри хранят строки). Вычислять результаты с плавающей запятой только для отображения и по требованию, если это возможно. Избегайте добавления больших и малых значений вместе, когда они являются плавающими, и избегайте прикованных вычислений в поплавках. Исправьте свою алгебру, чтобы избежать разделения до конца. Ruby также поддерживает тип данных Rational, который точно представляет дроби и может быть полезен.

Эти проблемы относятся к науке о "распространении ошибок с плавающей точкой", где вы можете найти дополнительную информацию, если вам нужно.

Ответ 4

Вам нужно преобразовать значения, которые находятся целыми центами (целые числа), в float (числа с десятичными знаками), чтобы математика привела к плавающему числу вместо целого числа.

Итак, в общем, он работает следующим образом:

some_integer.to_f / some_other_integer.to_f  # returns a float

Ответ 5

Даже если одно из значений Float, результат будет Float.

Также, если вы используете Rails и ваши хранилища данных в определенной модели, ActiveRecord имеет специальные методы, и вам не нужно вычислять самостоятельно.

Model.average("field_with_data")

Также доступны методы минимального, максимального, подсчета, суммирования.