2010-07-17 68 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来进行比较。