2015-02-08 69 views
0

我有需要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

回答

2

什麼是Rails的/ Postgres的使用浮動的限制?

PostgreSQL支持浮動使用標識符浮動真正點數。標識floatreal是同義詞。在大多數電腦上,floatreal會給你至少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

1

使用Decimal並指定精度您的數據庫規模,所以,你一定要有準確的計算。

Take a look at short example

+0

我還是不明白,爲什麼我不能用浮法這個任務 - 它們能夠處理的Rails之外,許多小數。這是Postgres的限制嗎? – garythegoat 2015-02-08 23:42:26