我对进出数据库后获得额外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
答案 0 :(得分:1)
9.46不能完全表示为IEEE double
- 精度浮点数。这有a great many consequences,但在这里意味着您获得了可以准确表示的值,并且最接近您放入的值。
如果你得到'9.46
'是至关重要的,请将其存储在TEXT
亲缘关系的列中(并注意你存储的是字符串,而不是“数字”)。< / p>
答案 1 :(得分:1)
我建议您阅读这篇文章:What Every Computer Scientist Should Know About Floating Arithmetic
该文章的tl; dr版本......
将无数多个实数压缩成有限数量的位 需要近似的表示。虽然有无限的 许多整数,在大多数程序中,整数计算的结果都可以 以32位存储。相反,给定任意数量的位, 大多数带有实数的计算都会产生数量 不能使用那么多位来精确表示。因此 浮点计算的结果通常必须按顺序舍入 以适应其有限的表示。这个舍入误差是 浮点计算的特征。
答案 2 :(得分:1)
我对ruby不是很熟悉,但不是使用
i.price = 9.46
尝试使用
i.price = BigDecimal.new('9.46')