如何修复Rails中这种奇怪的舍入错误?

Tin*_*n81 0 ruby ruby-on-rails ruby-on-rails-3 ruby-on-rails-3.2

我最近在Rails中遇到了这个奇怪的错误.

class PaymentsController < ApplicationController

  def new
    @payment = current_user.payments.build(:invoice_id => params[:invoice_id])
    @title = "Make payment" 
  end

end
Run Code Online (Sandbox Code Playgroud)
class Payment < ActiveRecord::Base

  attr_accessible :amount, :date, :invoice_id

  after_initialize :set_amount

  private

  def set_amount
    if new_record? && invoice.present?
      self.amount ||= invoice.amount_payable
    end
  end

end
Run Code Online (Sandbox Code Playgroud)

当我这样称呼这个动作时invoice......

<%= link_to "Make payment", new_payment_path(:invoice_id => invoice.id) %>
Run Code Online (Sandbox Code Playgroud)

...付款表单invoice在下拉字段中显示正确的预选(这是正确的).

amount在所有情况的约90%中,付款使用正确的金额填充.

但是,有时它不会填充amount_payable数据库中的2位数字,而是填充其他一些奇怪的值,例如:

87.31999999999999

(87.32SQLite数据库中存储的十进制类型值在哪里)

有人能告诉我是什么导致了这个舍入错误或者指向了正确的方向吗?

谢谢你的帮助.

顺便说一句,这是我的数据库架构:

create_table "invoices", :force => true do |t|
  t.decimal  "amount_payable", :precision => 8, :scale => 2
end
Run Code Online (Sandbox Code Playgroud)

Jes*_*ott 5

你永远不应该将Money存储为浮点数 - 这里发生的是浮点运算,这对于用钱计算是很常见的.

更好的一点是将所有内容存储为整数美分.因此,您可能在数据库中有一个"amount_in_cents"列,它是一个整数.

然后,为'amount'添加一个getter/setter,以便您可以在#amount所有地方使用.

class Payment < ActiveRecord::Base

  def amount
    amount_in_cents / 100.0
  end

  def amount=(other)
    self.amount_in_cents = (other * 100).to_i
  end
end
Run Code Online (Sandbox Code Playgroud)