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 a
What you're doing is called integer division, which discards any remainder, as it wouldn't be expressible in integers, e.g.:
1 / 3 # == 0
As other respondents have mentioned, you can force a floating point division. You need to force the first argument to be a float (1 here) by calling .to_f. The second argument will automatically be coerced into a float, i.e.:
1.to_f / 3 # ~ 0.3333...
Note that once you move to floating point numbers, the result, generally speaking, is no longer exact. This is why I put ~ 0.333.
The precise details are more involved. In binary floating point arithmetic, which is common in today's microprocessors, powers of 2 are still exact, I believe. But the integer 3, for example, is not longer represented exactly, but only within the precision of the floating point representation (typically 1E-16 or thereabouts for "double" precision).
Long story short, here is a rule of thumb: If you're dealing with money values, where precision matters (ever been noticed a 1 cent discrepancy on a phone bill?) don't store computed results, and don't store values in floating points. Instead use integer or decimal data types (which internally store strings). Compute floating point results only for display and on demand, if possible. Avoid adding large and small values together once they're floats, and avoid chained computations in floats. Rework your algebra to avoid divisions until the end. Ruby also supports a Rational data type which represents fractions exactly and may be useful.
These issues fall under the science of "floating point error propagation" which is where you can look up more information if you need.
Even if one of values are Float, result will be Float.
Also if you using Rails and your data stores in specific model, ActiveRecord has special methods and you don't need to calculate by yourself.
Model.average("field_with_data")
Also available minimum, maximum, count, sum methods.
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
You need to convert your values that are in whole cents (integers) to floats (numbers with decimals) so that the math will result in a floating number instead of an integer.
So in general it works like this:
some_integer.to_f / some_other_integer.to_f # returns a float
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.