私は私のRailsアプリケーションでこれを実行します。Railsの精度誤差
my_envelope.transactions.sum(:amount)
このSQLは、ログファイルに示されている:
SQL (0.3ms) SELECT SUM("transactions"."amount") AS sum_id FROM "transactions" WHERE (envelope_id = 834498537)
そして、この値が返されます。
<BigDecimal:1011be570,'0.2515999999 9999997E2',27(27)>
ご覧のとおり、値は25.159999です。それは25.16でなければなりません。同じSQLをデータベース上で自分で実行すると、正しい値が返されます。
浮動小数点数には精度問題があることがわかっていますが、BigDecimalが返されています。 SQLの列型は10進数です。私はsqlite3(3.6.17)とsqlite3-ruby(1.3.2)を使っています。何か案は?私が直接SQLite3の-rubyのインターフェースを使用して、これを実行したときにここで
アップデート1
は結果があります。
$ rails c test
Loading test environment (Rails 3.0.3)
irb(main):001:0> db = SQLite3::Database.new("db/test.sqlite3")
=> #<SQLite3::Database:0x5242020>
irb(main):002:0> db.execute("SELECT SUM(amount) FROM transactions WHERE envelope_id = 834498537")
=> [[25.159999999999997]]
この番号のクラスはFloatです。 btwの場合、合計値は-40.25、100、-34.59です。より多くの研究の後
アップデート2
、これはちょうどsqlite3の動作方法であることが判明しました。これはsqlite3-rubyにdouble(Ruby Floatと同じ)を返し、sqlite3-rubyはRailsにFloatとして渡します。次に、列の型が10進数なので、RailsはそれをBigDecimalに変換します。 Ruby 1.9より前では、Rubyはこの数値を丸めてしまい、問題は見えませんでした。
質問を更新して、使用しているデータベースサーバーとそのアクセスに使用しているドライバーを指定してください。 – noodl
これは私のテスト環境でsqlite3(3.6.17)を使っていて、sqlite3-ruby(1.3.2)を使っています。 – dontangg
sqlite3-rubyが集計の値を返すためにFloatを作成していると思われます。これを避けるために結果を文字列にキャストしてみてください。私はそれが理想的な解決策ではないことを知っていますが、それは少なくとも問題を特定するのに役立ちます。 – noodl