我注意到,当我存储双精度值时,例如 x = 0.56657011973046234 在 sqlite 数据库中,然后稍后检索它,我得到 y = 0.56657011973046201. 。根据 SQLite规范.NET规范 (我最初都懒得去读:)这是预料之中的,也是正常的。

我的问题是,虽然高精度并不重要,但我的应用程序会处理用户输入/选择代表基本 3D 信息的双精度数,然后对它们运行模拟以找到结果。此输入可以保存到 sqlite 数据库中,以便稍后重新加载和重新运行。

之所以会出现这种混乱,是因为一旦存储和重新加载,新创建的一系列输入显然会以与相同输入略有不同的方式进行模拟(因为双精度值已更改)。这是合乎逻辑的,但并不可取。

我还没有完全弄清楚如何处理这个问题,但与此同时,我想将用户输入限制/限制为可以精确存储在 sqlite 数据库中的值。所以如果用户输入 0.56657011973046234, ,它实际上转化为 0.56657011973046201.

然而,我无法弄清楚,给定一个数字,数据库中将存储什么值,缺乏实际存储和从数据库中检索它,这看起来很笨拙。有没有既定的方法来做到这一点?

有帮助吗?

解决方案

Double round 有一个带有指定位数的参数的实现。使用此方法四舍五入到 14 位(例如):rval = Math.Round(Val, 14)

然后在从数据库接收值时以及模拟开始时进行舍入,即。那么值匹配吗?

详情:

http://msdn.microsoft.com/en-us/library/75ks3aby.aspx

如果您不比较数据库中的值,而只是存储它们,则另一个想法是:为什么不简单地将它们存储为二进制数据呢?那么所有的位都会被逐字存储和恢复?

其他提示

答案可能是将双精度值存储为 17 位有效数字字符串。看看 SQLite 处理实数与处理整数的方式之间的区别。文本(为了简单起见,我将使用命令行界面进行说明):

sqlite> create table t1(dr real, dt varchar(25));
sqlite> insert into t1 values(0.56657011973046234,'0.56657011973046234');
sqlite> select * from t1;
0.566570119730462|0.56657011973046234

以真正的亲和力存储它是问题的原因——SQLite 只给你返回 15 位的近似值。如果您将其存储为文本,则可以使用 C# 程序检索原始字符串并将其转换回原始双精度值。

假设 SQL Lite 和 .NET 都正确实现了 IEEE 规范,如果在两侧使用相同的浮点类型,您应该能够获得相同的数字结果(因为从数据库传递时该值不应更改)到 C#,反之亦然)。

目前,您在 SQL Lite 中使用 8 字节 IEEE 浮点(单)(*),在 C# 中使用 16 字节浮点(双)。这 float C# 中的 type 对应于 8 字节 IEEE 标准,因此使用此类型代替 double 可以解决问题。

(*) SQL Lite 文档说 REAL 是 浮点值,存储为 8 字节 IEEE 浮点数.

您可以使用字符串将 # 存储在数据库中。就我个人而言,我已经完成了 winwaed 建议的在存储之前和从数据库获取之后进行舍入的操作(使用 numeric())。

我记得被银行家四舍五入烧伤了,但这可能只是不符合规范。

您可以将双精度值存储为字符串,并在将双精度值转换为字符串时使用往返格式,保证在解析时生成相同的值:

string formatted = theDouble.ToString("R", CultureInfo.Invariant);

如果您希望十进制输入值能够往返,则必须将它们限制为 15 位有效数字。如果您希望 SQLite 内部双精度浮点值进行往返,那么您可能会运气不佳;这需要打印至少 17 位有效数字,但据我所知,SQLite 最多打印 15 位(编辑: 也许 SQLite 专家可以证实这一点? 我刚刚阅读了源代码并追踪了它——我是对的,精度限制为 15 位。)

我在 Windows 上的 SQLite 命令界面中测试了您的示例。我插入了0.56657011973046234,然后选择返回0.566570119730462。在 C 中,当我将 0.566570119730462 分配给 double 并将其打印为 17 位数字时,我得到 0.56657011973046201;这与您从 C# 获得的值相同。0.56657011973046234 和 0.56657011973046201 映射到不同的浮点数,因此换句话说,SQLite double 不会往返。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top