避免浮动截断4
问题描述:
我有需要Float
属性和相应的表的活动记录模式:避免浮动截断4
# 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>
这个问题困扰我,因为我可以做以下的红宝石:
a = 123456789.123456789
#=> 123456789.123456789
a.class
#=> Float
a
#=> 123456789.123456789
什么是Rails的使用Float
的限制/ Postgres的?如果我想要5位小数的精确度,我应该使用Decimal
吗?
我用Rails 4.1.1和Postgres 9.3.5
答
什么你在这里看到的
PostgreSQL numeric data types
什么是Rails的/ Postgres的使用浮动的限制?
PostgreSQL支持浮动使用标识符浮动,真正和双点数。标识float和real是同义词。在大多数电脑上,float和real会给你至少6位的小数精度。这是小数精度的六位数字。
Test.last.size
#=> 271894000000.0
^^^^^^
在大多数计算机上,双会给你分数精确度至少15位。 Ruby's float相当于PostgreSQL的double,而不是PostgreSQL的real。
如果我想要5位小数的精确度,我应该使用小数吗?
短语我想要的5个小数点准确性 [原文]没有很好地转化为浮点数据类型。当你写这样的东西
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
没有截断或者四舍五入,严格地说。这是“近似误差”。值271893999999.99997
不在数据库域float
中,因此PostgreSQL使用该域中最接近的值为。该值恰好是271894000000.0
。
PostgreSQL numeric data types
我还是不明白,为什么我不能用浮法这个任务 - 它们能够处理的Rails之外,许多小数。这是Postgres的限制吗? – garythegoat 2015-02-08 23:42:26