Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Working with decimals in Ruby on Rails 3

I'm trying to calculate the average net price of a product. I have, in my Product model :total_sold and :total_net_revenue. Doing straight division in the method seems to always result in 0. I resorted to using BigDecimal as I figured that was the problem ... but with my latest iteration of the code below, I'm still getting zero when the answer comes out to a decimal.

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

Net revenue is in cents, which is why I divide by 100. Can someone point out what I'm doing wrong or should do?

like image 883
Slick23 Avatar asked Jan 19 '11 01:01

Slick23


People also ask

How do you round to 2 decimal places in Ruby?

Ruby has a built in function round() which allows us to both change floats to integers, and round floats to decimal places. round() with no argument will round to 0 decimals, which will return an integer type number. Using round(1) will round to one decimal, and round(2) will round to two decimals.

What is precision and scale in decimal in rails?

For clarity's sake: the precision is the number of significant digits, while the scale is the number of digits that can be stored following the decimal point. For example, the number 123.45 has a precision of 5 and a scale of 2. A decimal with a precision of 5 and a scale of 2 can range from -999.99 to 999.99.

How do you round a value in rails?

You can simply use x. round(2) when displaying the number - that will always display two decimal places. It's generally recommended to store prices as integers in the backend database because they are handled better when you need a really high level of precision. In this case though, you can choose to go either way.


2 Answers

total_net_revenue / total_sold

or

total_net_revenue / total_sold / 100.0

or

total_net_revenue.to_f / total_sold / 100

These three methods give an increasing amount of precision, if you want it. Remember that "average price" is "average price / sale. That's money-per-item so you will want to do the division in that specific order.

like image 89
DigitalRoss Avatar answered Nov 09 '22 23:11

DigitalRoss


First: You are dividing the wrong way.

100 items / $150 = .667 items per dollar

vs.

$150 / 100 items = $1.50 per item

Second: Like other languages, you need to force one of the numbers in the equation to be a decimal so that the result is cast as one as well. Since your revenue is a whole number, that meant all three values were whole numbers, which means you got a whole number as a result. To get a decimal, cast one of them as a floating-point number.

In other words, to get what you need, do this:

price_per_item = (total_net_revenue.to_f / 100) / total_sold
like image 26
Shaun Avatar answered Nov 10 '22 00:11

Shaun