Mat*_*w H 0 ruby activerecord ruby-on-rails
我试图在我的模型的after_update回调中重新计算百分比.
def update_percentages
if self.likes_changed? or self.dislikes_changed?
total = self.likes + self.dislikes
self.likes_percent = (self.likes / total) * 100
self.dislikes_percent = (self.dislikes / total) * 100
self.save
end
end
Run Code Online (Sandbox Code Playgroud)
这不起作用.百分比总是以100或0出现,这完全破坏了一切.
我在哪里滑倒?我保证self.likes和self.dislikes正在递增.
当您将整数除以整数(也称为整数除法)时,大多数编程语言(包括Ruby)都假定您希望结果为整数.这主要是由于历史,因为对于数字的低级表示,整数与具有小数点的数字非常不同,并且整数除法要快得多.所以你的百分比,一个介于0和1之间的数字,其十进制被截断,因此变为0或1.当乘以100时,变为0或100.
如果除法中的任何数字不是整数,则不执行整数除法.替代方案是带小数点的数字.有这样的几种类型的数字,但通常它们被称为浮点数,而在Ruby中,最典型的浮点数是Float类.
1.0.class.ancestors
# => [Float, Precision, Numeric, Comparable, Object, Kernel]
1.class.ancestors
# => [Fixnum, Integer, Precision, Numeric, Comparable, Object, Kernel]
Run Code Online (Sandbox Code Playgroud)
在Rails的模型中,浮点数用Ruby Float类表示,而decimal用Ruby BigDecimal类表示.不同之处在于BigDecimals更准确(即可用于赚钱).
通常,您可以将您的数字"强制转换"为浮点数,这意味着您将不再进行整数除法.然后,如果需要,可以在计算后将其转换回整数.
x = 20 # => 20
y = 30 # => 30
y.to_f # => 30.0
x.class # => Fixnum
y.class # => Fixnum
y.to_f.class # => Float
20 / 30 # => 0
20 / 30.0 # => 0.666666666666667
x / y # => 0
x / y.to_f # => 0.666666666666667
(x / y.to_f).round # => 1
Run Code Online (Sandbox Code Playgroud)
在你的情况下,假设你想要整数结果(即42%为42%),我认为最简单的方法是在除法之前乘以100.这会将你的小数点推到最右边,就像它将要去的那样,在分割之前,这意味着你的数字就像它将得到的一样准确.
before_save :update_percentages
def update_percentages
total = likes + dislikes
self.likes_percent = 100 * likes / total
self.dislikes_percent = 100 * dislikes / total
end
Run Code Online (Sandbox Code Playgroud)
笔记:
self你只需要它们来分配以消除创建局部变量的歧义,并且当你有一个局部变量来消除歧义时你想要调用方法而不是引用变量