3

我对进出数据库后获得额外 0.000000000000000001 (左右)的 2 位小数感到有些困惑。

这就是我所做的:(Rails 3.2.8)

创建了一个迁移:

class CreateItems < ActiveRecord::Migration
  def change
    create_table :items do |t|
      t.column :price, :decimal, :precision => 16, :scale => 2
    end
  end
end

创建了一个模型:

class Item < ActiveRecord::Base
end

然后:

$ rails c
>> i = Item.new
>> i.price = 9.46
>> i.save
>> Item.first.price
=> #<BigDecimal:46b3768,'0.9460000000 000001E1',27(45)>

这是一个 SQLite 数据库,在那里看起来一切正常:

$ rails db
>> select * from items;
1|9.46

请注意,我注意到发生这种情况的唯一数字是 9.46。额外的 0.00000000000001 是从哪里来的?


编辑我知道如果没有小错误,某些数字的浮点表示是不可能的。但是为什么不Item.first.price等于BigDecimal.new('9.46')呢?SQLite 是否存储一个浮点数而不是一个整数,并且它应该被除以 10 的次数(这就是我对小数列的期望)?或者 ActiveRecord 中是否有一些我不知道从数据库中检索值的问题?见下文:

$ rails c
>> decimal = BigDecimal.new('9.46')
>> Item.first.price == decimal
=> false
4

3 回答 3

1

9.46 不能完全表示为 IEEEdouble精度浮点数。这有很多后果,但这意味着你得到的值是完全可表示的,并且最接近你输入的值。

如果取出 ' 9.46' 至关重要,请将其存储在具有TEXT关联性的列中(并注意您存储的是字符串,而不是“数字”)。

于 2012-10-09T22:07:30.807 回答
1

我建议阅读这篇文章:每个计算机科学家都应该知道的关于浮点运算的知识

这篇文章的 tl;dr 版本...

将无限多个实数压缩为有限位数需要近似表示。尽管整数有无限多,但在大多数程序中,整数计算的结果可以存储在 32 位中。相反,给定任何固定位数,大多数实数计算将产生无法使用那么多位精确表示的量。因此,浮点计算的结果必须经常四舍五入以适应其有限表示。这种舍入误差是浮点计算的特征。

于 2012-10-09T22:08:30.213 回答
1

我对红宝石不是很熟悉,但不是使用

i.price = 9.46

尝试使用

i.price = BigDecimal.new('9.46')
于 2012-10-09T22:08:50.383 回答