在Ruby on Rails 3中使用小数

时间:2011-01-19 01:17:01

标签: ruby-on-rails ruby 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的原因。有人可以指出我做错了什么或应该做什么?

5 个答案:

答案 0 :(得分:13)

total_net_revenue / total_sold

total_net_revenue / total_sold / 100.0

total_net_revenue.to_f / total_sold / 100

如果您需要,这三种方法可以提供更高的精度。请记住,“平均价格”是“平均价格/销售。这是每件物品的金额,因此您将希望按特定顺序进行分割。

答案 1 :(得分:12)

第一:你分道错误。

100件/ $ 150 = .667件商品

VS

$ 150/100件商品=每件1.50美元

第二:与其他语言一样,您需要强制等式中的一个数字为小数,以便将结果转换为一个。由于您的收入是一个整数,这意味着所有三个值都是整数,这意味着您得到一个整数。要获得小数,请将其中一个作为浮点数。

换句话说,要获得所需,请执行以下操作:

price_per_item = (total_net_revenue.to_f / 100) / total_sold

答案 2 :(得分:8)

你所做的是整数除法,它会丢弃任何余数,因为它在整数中是不可表达的,例如:

1 / 3 # == 0

正如其他受访者所提到的,您可以强制进行浮点划分。你需要通过调用.to_f强制第一个参数成为float(这里是1)。第二个参数将自动强制转换为浮点数,即:

1.to_f / 3 # ~ 0.3333...

请注意,一旦移动到浮点数,一般来说结果就不再精确了。这就是为什么我把~0.333。

准确的细节更多涉及。在二进制浮点运算中,这在今天的微处理器中是常见的,我相信2的幂仍然是精确的。但是,例如,整数3不再精确表示,而是仅在浮点表示的精度范围内(通常为1E-16或“双精度”精度)。

长话短说,这是一条经验法则:如果你正在处理货币价值,精确度很重要(曾经注意到电话账单上有1美分的差异?)不存储计算结果,并且不要t以浮点存储值。而是使用整数或十进制数据类型(在内部存储字符串)。如果可能,计算浮点结果仅用于显示和按需。避免在浮点数时将大值和小值相加,并避免浮点数中的链式计算。重写你的代数以避免分裂直到结束。 Ruby还支持Rational数据类型,它完全代表分数并且可能很有用。

这些问题属于“浮点错误传播”的科学,如果需要,您可以在这里查找更多信息。

答案 3 :(得分:3)

您需要将整数分(整数)的值转换为浮点数(带小数的数字),这样数学运算将产生浮点数而不是整数。

所以一般来说它的工作原理如下:

some_integer.to_f / some_other_integer.to_f  # returns a float

答案 4 :(得分:0)

即使其中一个值为Float,结果也是Float。

此外,如果您在特定模型中使用Rails和数据存储,ActiveRecord有特殊方法,您无需自己计算。

Model.average("field_with_data")

还提供最小,最大,计数,求和方法。