【问题标题】:Difference in represtantion of floating point number in double type property (class) and in double type field (SQL query)double 类型属性(类)和 double 类型字段(SQL 查询)中浮点数表示的差异
【发布时间】:2018-10-13 19:17:08
【问题描述】:

我有一个代表特定数据库表的类。该类中的一些属性以及数据库表中的一些字段是double类型。

在这里,在类中,您会看到一些属性具有 1 个有效数字,例如。 T12、T13、T18、T19(0.8、12.1 等)。

但是,当我将此类插入数据库表时,Linq2Db 会产生这样的查询:

当我查看数据库表时,字段包含正确的一位有效数字值:

我非常了解浮点数如何以二进制格式表示。我已经读过文章Why Are Floating Point Numbers Inaccurate?。

我的问题:

  1. 为什么类中的双类型表示 (T12 = -0.8) 与“Linq2Db”操作后的表示 (T12 = -0.800...004) 不同?

  2. 在数据库中保存这样的双精度值是否安全? (我想防止出现不准确的值)

  3. 为什么查询中的值和数据库表中的值存在差异?

编辑 1:

这是数据库查询的结果。 15 位有效数字(全 0)与 17 位有效数字(上图)。 Access 不能显示超过 15 位数字。

编辑 2:

Decimal               0.8
Class Double          0.8
Floating-Point Double 0.8000000000000000444089209850062616169452667236328125
Floating-Point Single 0.800000011920928955078125 (for comparison)
SQL Query             0.80000000000000004 (!)  => 17 digits after point (why?)
MS Access             0.800000000000000 = 0.8  => 15 digits after point

为什么类中的double类型可以是0.8,但是没有任何操作或算术运算的相同值插入到数据库中为0.80000000000000004? 'Linq2Db' 用它做什么?

【问题讨论】:

  • 可能,完整的值存储在数据库中。在显示一位有效数字时,存储完整值。尝试查询该值,您可能会得到相同的值 Linq2Db 插入。如果您想以一定的精度存储特定值,我建议使用 Decimal 数据类型,或者在使用 Access 和 mdb 文件时使用 Currency 数据类型。
  • 这里“安全”的定义是什么?如果您不希望不准确,请不要选择浮动。使用 decimal 类型,但要了解存在细微的性能差异,这就是您为数据准确性而牺牲的。

标签: c# sql ms-access precision linq2db


【解决方案1】:

linq2db 使用 17 位有效数字将 double 值表示为十进制 SQL 文字,因为它是允许您将 double 值往返于十进制表示并安全返回而不会丢失精度的最少位数。

在您的情况下没有必要,因为 Access(和 Excel BTW)不支持超过 15 个有效数字的双精度类型。

【讨论】:

    【解决方案2】:

    如果您想要精确表示十进制值,请切换到 decimal 而不是浮点表示。

    像 0.8 这样的数字 无法使用固定数量的二进制十进制数字准确表示(但是,0.5 和 0.75 可以)。您实际看到的内容取决于显示结果的应用程序,而不是它的存储方式。

    因此,只需使用与您真正想要的数据类型相对应的数据类型,即定点小数。

    【讨论】:

    • 查询数据后,我看到完美的舍入值,以 0 结尾。唯一的区别是,Ms Access 在点后最多可以显示 15 位数字,其中 Visual Studio 的屏幕显示 17 位数字,最后一位不是 0。请参见此处:link。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-11
    相关资源
    最近更新 更多