Android上的SQLite3没有正确添加浮点数

时间:2016-07-18 15:37:29

标签: android database sqlite

我在Android上运行SQLite3上的一些简单语句时遇到了一些麻烦。

例如:

SELECT 1234 + 0.001

应该返回1234.001,对吗?但是,SQLite在仿真器(v21)和真实设备(v19)上都返回1234。

考虑到1234存储在名为Field1的列上,在Table1上键入REAL,我尝试了以下所有选项:

SELECT Field1 + 0.001 FROM Table1

SELECT (Field1 * 1.000)  + 0.001 FROM Table1

SELECT CAST(Field1 as FLOAT) + 0.001 FROM Table1

SELECT CAST(Field1 as REAL) + 0.001 FROM Table1

SELECT Field1 + 0.001 from Table1

SELECT CAST((Field1 + 0.001) as REAL) FROM Table1

似乎没有任何作用,在每一个案例中我都得到1234而不是1234.001。我需要在查询中从1234获得1234.001,但SQLite3并没有帮助。

我刚发现的另一件事:如果" Field1" < = 999,SELECT按预期工作,结果得到999.001。任何> = 1000都会给我一个整数。

你能帮我解决一下这个问题吗?

enter image description here

2 个答案:

答案 0 :(得分:0)

实际上,我发现问题并非如此。这些数字被视为x.001,但没有这样显示。在内部,数字正在以二进制形式正确存储,但并未显示所有小数部分。在将它们作为文本转换后,我能够看到小数部分就在那里。

无论如何,谢谢你的时间和答案。

enter image description here

答案 1 :(得分:-1)

这是一个精度问题以及数字如何存储在计算机中或sqlite3中的问题。数字以二进制格式存储,这意味着通过将十进制数转换为二进制数,您会失去一些精确度(实数)read more here。现在,如果您希望在示例中添加1234.001,您有什么选择?

A)将数字存储为字符串。

您始终可以存储值' 1234'和' 0.001'因为VARCHAR和JAVA代码将此值解析为BigDecimals并在那里执行添加。有关解析的更多信息,请查看此link。这种方法的缺点是它会在数据库中消耗更多的存储空间,而解析操作也不会那么快。在使用此方法之前,请考虑此缺陷是否会对应用程序的性能产生负面影响。

B)建立MAXIMUM_PRECISION并将它们存储为INTEGER。

默认情况下,SQLITE3使用8个字节存储INTEGER。这意味着您可以存储的最大整数大小为10 ^ 19。现在,通过存储整数,你不会失去精度;所以我们可以利用这一点。让我们说你的MAXIMUM_PRECISION是0.001(如你的例子中)那么你需要将这个数乘以一千来得到1.那么,如果不是将1234.001表示为实数,我们将其表示为1234001为int ?这样我们就可以安全地将int存储在sqlite3中,并确保操作正常。在您的代码中,您可以稍后将数字解析为String并对其进行格式化以将其显示给用户,或者您可以将其解析为BigDecimal以保持精度。当然,这将限制你的最大数量为10 ^ 16;再次检查您的要求,看看这个技巧是否适用于您的应用。请注意,类似的技巧用于存储货币而不会丢失sqlit3中的精度,有关详细信息,请参阅:this link