2010-07-17 71 views
4

我把一個漂浮在一個基於Android的SQLite數據庫,就像這樣:SQLite查詢哪裏有浮點數的子句失敗?

private static final String DATABASE_CREATE = 
    "create table " + DATABASE_TABLE + " (" 
        + KEY_ID + " integer primary key autoincrement, " 
        + KEY_FLOAT + " REAL, " + ... 
... 

content.put(KEY_FLOAT, 37.3f); 
db.insert(DATABASE_TABLE, null, content); 

當我查詢表:

Cursor cursor = db.query(false, DATABASE_TABLE, 
     new String[] { KEY_ID, KEY_FLOAT, ... }, 
     KEY_LATITUDE + "=37.3", 
     null, null, null, null, null); 

光標回來空。如果我將float的值更改爲37.0,它將正常工作,並返回光標中的記錄。

我在一些長度測試此,從「REAL」爲「浮動」,等等改變數據庫列規範AS只要我有小數點之後的任何小數部分時,光標返回空。到底是怎麼回事?

提前致謝!

+1

建議閱讀:http://floating-point-gui.de/ – 2010-07-17 07:14:18

回答

8

37.0是二進制浮點精確表示的,所以你不要有任何的正常問題。 37.3是精確表示的 - 你的查詢不匹配,因爲在數據庫中的值是不完全的37.3。

選項:

  • 使用基於十進制數字類型,如果SQLite中存在這樣的事情(我會在一分鐘內檢查)
  • 讓您的查詢中使用的公差,例如「LATITUDE> 37.29和LATITUDE < 37.31」。恐怕,比較二進制浮點值以獲得精確的相等性只是要求麻煩。

編輯︰我剛剛檢查the docs,它看起來像SQLite不支持十進制非整數類型。我會在上面留下這個建議,因爲它與其他數據庫中的相同問題相關。

編輯:有效滾動自己的數值類型帕斯卡的解決方案是一個很好的在許多情況下。計算出你想要的精度水平,並相應地進行乘法/除法......所以如果你想要精確到2個小數位,當你存儲一個值時乘以100,然後在取出它之後除以100。當然,您的查詢需要採用「相乘」的形式。

+0

謝謝喬恩。我已經意識到浮點惡魔,但拒絕接受他們可以以如此小的精度進入:我嘗試應用val =(Math.round(val * 1000))/ 1000;在進入數據庫之前,這是無用的... more @ pascal。 – DJC 2010-07-17 17:16:31

+0

@DJC:試試看看0.1應該如何用二進制表示......你可以非常接近,但你永遠不會得到*精確到0.1。 – 2010-07-17 17:29:51

1

誠然,這是一個壞主意,平等比較浮點值。

不管怎樣,我看到SQLite uses 8-byte floating point values(這就像DOUBLE),所以奇怪的是37.0被認爲等於37.3。除非你爲你的例子修改了實際代碼中使用的值?

你可以存儲你的LATITUDE爲整數,在程度上的十分之一,運用自己的精度,並在讀取轉換值/寫...

+2

我認爲「它適用於37.0」位已經改變了這兩個部分。 – 2010-07-17 07:27:18

+0

謝謝pascal。我已經應用了您的解決方案,將值乘以1000,並將整數部分放入數據庫中,這很好。不幸的是,我用來爲UI填充列表的android.widget.SimpleCursorAdapter當然不知道需要將數字轉換回來,所以我必須調整它,否則轉移到存儲字符串。我很想做後者,認爲按照我所要求的精度,它們在存儲和精度上可能與雙打差不多...... – DJC 2010-07-17 17:10:35

+1

哦,是的..僅供參考,問題發生在百分之一..不是十分之一..我已經簡化了這個例子 :) – DJC 2010-07-17 17:12:43

1

我試着用<column> BETWEEN <min> AND <max>和它的工作,寬容LATITUDE > 37.29 AND LATITUDE < 37.31沒爲我工作。但我嘗試了BETWEEN這個提示。

我的意見:

  1. 當我有一個記錄,大於(>)沒有工作。
  2. 如果有一個以上的記錄,大於(>)完美。
0

以下的事情爲我工作:

設置列類型爲Double並插入使用Double數據類型爲Java行。不知何故,雙工...

0

我面臨同樣的問題。我的Sqlite列的類型是FLOAT。我不得不將類型爲Float的Java變量作爲double來進行比較。