奇怪的舍入问题

时间:2016-11-25 15:02:40

标签: ruby-on-rails postgresql activerecord floating-point decimal

使用小数和浮点数发生了一些非常奇怪的事情,我无法理解为什么或在哪里(ruby / rails / postgresql)。

给出带有小数列的购物表 - 总计

p1 = Purchase.where(total: 5.99).first_or_create
p2 = Purchase.where(total: 5.99).first_or_create

[p1.id, p2.id] # => [1, 2]

p3 = Purchase.where(total: 5.99.to_d).first_or_create
p4 = Purchase.where(total: 5.99.to_d).first_or_create

[p3.id, p4.id] # => [1, 1]

无论是小数还是浮点数,Ruby和postgresql都没有完全代表5.99的问题:

5.99.to_s         # => "5.99"
5.99.to_d.to_s    # => "5.99"
5.99 == 5.99.to_d # => true

SELECT CAST(5.99 AS DECIMAL) AS decimal, CAST(5.99 AS FLOAT) AS float;
  #  decimal | float 
  # ---------+-------
  #     5.99 |  5.99
  # (1 row)

SELECT CAST(5.99 AS DECIMAL) = CAST(5.99 AS FLOAT) AS equal;
  #  equal 
  # -------
  #  t
  # (1 row)

最重要的是,其他一些值不会发生这种情况:

p5 = Purchase.where(total: 5.75).first_or_create
p6 = Purchase.where(total: 5.75).first_or_create
p7 = Purchase.where(total: 5.75.to_d).first_or_create

[p5.id, p6.id, p7.id] # => [3, 3, 3]

1 个答案:

答案 0 :(得分:0)

这结果是铁轨的回归。它可以用5.0.0.1重现吗???并且已经过了5.1.0.0 ???。

我把它分成两半,发现this commit是解决问题的那个。这是相关的issue

修复似乎是停止使用pg gem的float编码器。