何时使用小数或双精度

时间:2016-04-13 04:35:58

标签: sql .net double decimal precision

快速旁白:我将使用" Float"引用.Net浮点数和只有7位有效数字的SQL浮点数。我将使用" Double"引用.Net double和带有15位有效数字的SQL float。我也意识到这与其他关于小数/双打的帖子非常相似,但这些帖子的答案确实不一致,我真的想要一些针对我特定情况的建议......

我是一个正在重写旧应用程序的团队的一员。原始应用程序使用浮动(7位数)。这当然引起了问题,因为应用程序进行了大量计算并且非常快速地累积了四舍五入的错误。在某些时候,许多浮动都改为小数。后来,数据库中的浮点数(7)全部变为双打(15)。之后,我们在涉及双精度的计算中又出现了几个错误,并且它们也被改为小数。

今天,我们数据库中所有浮点数的1/3都是小数,其余的是双精度数。我的团队希望"标准化"我们在数据库中的所有浮点数(以及新的.Net代码)只能使用小数或双精度数,除非必须使用另一个。团队的大多数人都使用小数;我是团队中唯一提倡使用双打而不是小数的人。这就是为什么......

  1. 数据库中的大多数数字仍然是双倍的(尽管许多应用程序代码仍然使用浮点数),并且将所有浮点数/双精度数更改为小数数将花费更多的努力
  2. 对于我们的应用,所存储的字段都不是"确切的"十进制数量。它们都不是货币数量,而且大多数都代表某种“天然的”#34;测量(例如质量,长度,体积等),因此双倍的16位有效数字已经比我们的初始测量精确得多。
  3. 许多表都将测量值存储在两列中:1表示值; 1表示计量单位。这可能导致单个列中值之间的巨大差异。例如,一列可以以pCi / g或Ci / m3(1 Ci = 1000000000000 pCi)的形式存储值。由于单个十进制列中的所有值必须具有相同的 scale (即...小数点前后的分配位数),我担心我们会有溢出和四舍五入的问题。
  4. 我的队友争辩说:

    1. 双打不是准确,也不是精确小数,因为它们无法完全代表1/10而且他们只有有16位有效数字。
    2. 即使我们没有跟踪资金,该应用程序也是一个库存系统,可以跟踪材料(主要是克数),并且需要尽可能准确"。
    3. 即使将花车改为双打,我们仍然会因使用双打的计算结果不佳。将这些列(和应用程序代码)更改为小数会导致这些计算产生预期结果。
    4. 我坚信,由浮点数引起的原始问题只有7位有效数字和简单算术(例如10001 * 10001)导致数据快速消耗掉他们拥有的几个有效数字。我不认为这与二进制浮点数只能近似十进制值有什么关系,我相信使用双精度可以解决这个问题。

      我认为双打问题的出现是因为在计算中沿着小数点使用了双精度值,这些值在数据类型之间来回转换。其中许多计算将在计算中的中间步骤之间进行舍入!

      我试图说服我的团队不要让阳光下的所有东西变成小数。无论如何,数据库中的大多数值都不会超过5或6位有效数字。不幸的是,我的团队中其他成员的排名太高了,他们的看法却截然不同。

      那么,我的问题是......

      1. 我什么都不担心?在具有近200个数据库表,数百个事务处理和5到6年的重写计划的应用程序中,几乎只使用小数而不是双打,是否有任何真正的危害?
      2. 使用小数实际上解决了双倍的问题吗?根据我的研究,小数和双精度都容易受到涉及任意分数的舍入误差的影响(例如增加1/3),并且考虑到这一点的唯一方法是将某个容差内的任何值视为"等于&# 34;比较双打和/或小数时。
      3. 如果使用双打更合适,我可以提出哪些参数(除了我已经提出的参数)可以说服我的团队不要将所有更改为小数?

2 个答案:

答案 0 :(得分:1)

当您需要完全准确的基数为10的数字(财务数据,成绩)时,请使用decimal

当您存储自然不精确的数据(测量,温度),想要更快的数学运算时,请使用doublefloat,并且可以牺牲少量的不精确度。

由于您似乎只存储各种测量(无论如何都有一些精度),float将是合理的选择(如果您需要超过7位数的精度,则为double)。

  

使用小数实际上解决了双倍的问题吗?

不是真的 - 数据只会与用于生成数据的测量结果一样准确。你真的可以说测量的数量是123.4567克吗?用于测量的设备是否具有这种精确度?

为了解决“舍入误差”,我认为你无法确切地说1234.5克的测量值是否正好正好中途 - 它可能很容易就是1234.49克,这将会向下舍入反正。

您需要决定的是“可接受的精度水平”,并始终将该精度作为最后一步。不要对数据或中间计算进行舍入。

  

如果使用双打更合适,我可以提出什么参数(除了我已经提出的参数)可以说服我的团队不要将所有内容都改为小数?

除了转换时间外,你唯一真正牺牲的就是速度。了解速度的唯一方法是尝试两种方式并衡量差异。

答案 1 :(得分:0)

你最好尽量不要失去精确度。我想我的错可能说服你选择加倍。

===>我做了一些错误的算术,它返回了一些非常奇怪的东西: 给定0.60,它会返回5

int get_index(double value) {
    if (value < 0 || value > 1.00)
        return -1;
    return value / 0.10;
}

我修好了:

int get_index(double value) {
    if (value < 0 || value > 1.00)
        return -1;
    return (value * 100000000) / (0.10 * 100000000);
}