我有一个Active Record模型,它采用Float
属性和相应的表格:
# app/models/test.rb
class Test < ActiveRecord::Base
end
# db/schema.rb
ActiveRecord::Schema.define(version:20150208185300)
enable_extension "plpgsql"
create_table "tests", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
t.float "size"
end
end
当我坚持测试时,一切看起来都很好:
Test.create(size: 271893999999.99997)
#=> #<Test id: 1, created_at: "2015-02-07 19:43:22", updated_at: "2015-02-07 19:43:22", size: 271893999999.99997>
然而,当检索测试的大小时,它会被截断为:
Test.last.size
#=> 271894000000.0
当我创建它时,尽管输出有误导性,但在持续时也会被截断:
Test.last
#=> #<Test id: 1, created_at: "2015-02-07 19:43:22", updated_at: "2015-02-07 19:43:22", size: 271894000000.0>
这个问题困扰我,因为我可以在Ruby中执行以下操作:
a = 123456789.123456789
#=> 123456789.123456789
a.class
#=> Float
a
#=> 123456789.123456789
在Rails / Postgres中使用Float
有什么限制?如果我想要5个小数点的准确度,我应该使用Decimal
吗?
我正在使用Rails 4.1.1和Postgres 9.3.5
答案 0 :(得分:2)
在Rails / Postgres中使用Float有什么限制?
PostgreSQL使用标识符 float , real 和 double 支持浮点数。标识符 float 和 real 是同义词。在大多数计算机上, float 和 real 将为您提供至少6位小数精度。这是十进制精度的六位数。
Test.last.size
#=> 271894000000.0
^^^^^^
在大多数计算机上, double 将为您提供至少15位小数精度。 Ruby's float相当于PostgreSQL的 double ,而不是PostgreSQL的真实。
如果我想要5个小数点的准确度,我应该使用Decimal吗?
短语我想要5个小数点的准确度 [sic]并不能很好地转换为浮点数据类型。当你写这样的东西时
Test.create(size: 271893999999.99997)
你不是要求PostgreSQL在小数点右边五位数。您要求小数精度的17位数。浮点数据类型不太可能提供那么多精度。
您需要使用任意精度数据类型,而不是浮点数。在数据库方面,它看起来像
numeric(17, 5)
decimal(17, 5)
这两个声明都给你17位精度,小数点右边最多5位数。
在Rails迁移中,您可能会这样做。
add_column :your_table, :your_column, :decimal, :precision => 17, :scale => 5
<小时/> 你在这里看到了什么
Test.last.size
#=> 271894000000.0
严格来说,不是截断或舍入。它是近似的错误&#34;。值271893999999.99997
不在数据库域float
中,因此PostgreSQL使用该域中 的最接近值。该值恰好是271894000000.0
。
<小时/> PostgreSQL numeric data types
答案 1 :(得分:1)
使用Decimal
并在数据库中指定 precision 和 scale ,这样您就可以确保计算准确。