避免 Rails 中的 Float 截断 4
Avoiding Float truncation in Rails 4
我有一个 Active Record 模型,它采用 Float
属性和相应的 table:
# 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
使用Decimal
,并在数据库中指定precision和scale,确保计算准确。
What are the limits of using Float in Rails/Postgres?
PostgreSQL 使用标识符 float、real 和 double 支持浮点数。标识符 float 和 real 是同义词。在大多数计算机上,float 和 real 将为您提供至少 6 位小数精度。这就是六位小数精度的样子。
Test.last.size
#=> 271894000000.0
^^^^^^
在大多数计算机上,double 将为您提供至少 15 位小数精度。 Ruby's float 相当于 PostgreSQL 的 double,而不是 PostgreSQL 的 real.
Should I be using Decimal instead if I want the accuracy of 5 decimal points?
短语我想要 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
严格来说,这不是截断或舍入。是 "error of approximation"。值 271893999999.99997
不在数据库域 float
中,因此 PostgreSQL 使用该域中 是 的最接近值。该值恰好是 271894000000.0
.
PostgreSQL numeric data types
我有一个 Active Record 模型,它采用 Float
属性和相应的 table:
# 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
使用Decimal
,并在数据库中指定precision和scale,确保计算准确。
What are the limits of using Float in Rails/Postgres?
PostgreSQL 使用标识符 float、real 和 double 支持浮点数。标识符 float 和 real 是同义词。在大多数计算机上,float 和 real 将为您提供至少 6 位小数精度。这就是六位小数精度的样子。
Test.last.size
#=> 271894000000.0
^^^^^^
在大多数计算机上,double 将为您提供至少 15 位小数精度。 Ruby's float 相当于 PostgreSQL 的 double,而不是 PostgreSQL 的 real.
Should I be using Decimal instead if I want the accuracy of 5 decimal points?
短语我想要 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
严格来说,这不是截断或舍入。是 "error of approximation"。值 271893999999.99997
不在数据库域 float
中,因此 PostgreSQL 使用该域中 是 的最接近值。该值恰好是 271894000000.0
.
PostgreSQL numeric data types