关于sql:何时使用小数或双精度数

When to use decimals or doubles

快速旁白:我将使用"float"这个词来指代.NET float和只有7位有效数字的SQL float。我将使用单词"double"来指代.NET double和具有15个有效数字的SQL float。我也意识到这与其他一些关于小数/双精度的帖子非常相似,但是这些帖子上的答案确实不一致,我真的想要一些针对我具体情况的建议…

我是正在重写旧应用程序的团队的一员。最初的应用程序使用浮点数(7位数)。这当然引起了一些问题,因为应用程序进行了大量的计算,并且很快积累了舍入误差。在某个时刻,这些浮点数中的许多都变为小数。后来,数据库中的浮点数(7)都变成了双精度数(15)。在那之后,我们在涉及双精度的计算中还有几个错误,它们也被改为小数。

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

  • 数据库中的大多数数字仍然是双精度的(尽管许多应用程序代码仍然使用浮点),将所有的浮点/双精度都改为小数要付出更多的努力。
  • 对于我们的应用程序,存储的字段都不是"精确"的十进制数量。它们都不是货币量,大多数都代表某种"自然"测量(例如质量、长度、体积等),所以双精度16位有效数字已经比我们最初的测量更精确了。
  • 许多表的度量值存储在两列中:1表示值,1表示度量单位。这可能会导致单个列中的值在比例上存在巨大差异。例如,一列可以存储PCI/G或CI/M3(1 CI=10000000000 PCI)的值。因为一个十进制列中的所有值必须具有相同的小数位数(即…分配的小数点前后的位数),我担心会出现溢出和舍入问题。
  • 我的队友认为:

  • 由于双精度数不能精确地表示1/10,并且只有16个有效数字,因此双精度数不如小数精确。
  • 即使我们不跟踪钱,应用程序是一个库存系统,保持跟踪材料(大部分是克数量),它需要"尽可能准确"。
  • 即使在将浮点数更改为双精度数之后,我们仍然会从使用双精度数的计算中得到不好的结果。将这些列(和应用程序代码)更改为小数会导致这些计算产生预期的结果。
  • 我深信,由于浮点数只有7个有效数字而导致的原始问题,以及简单的算术(例如10001*10001),导致它们对数据快速用尽它们所拥有的几个有效数字。我不认为这与二进制浮点数只能近似十进制值有关,我相信使用双精度数可以解决这个问题。

    我相信双精度数的问题是因为在计算中,双精度数与小数一起使用,在数据类型之间来回转换值。这些计算中的许多都是在中间步骤之间进行的!

    我试图说服我的团队不要把太阳底下的一切都变成小数。数据库中的大多数值的有效位数都不超过5或6位。不幸的是,我的团队中其他成员对事情的看法大相径庭。

    所以,我的问题是…

  • 我是不是什么都不担心?在一个拥有近200个数据库表、数百个事务和5到6年的重写计划的应用程序中,使用几乎只使用小数而不是双精度数是否有真正的危害?
  • 使用小数真的能解决双倍不能解决的问题吗?根据我的研究,小数和双精度都容易受到涉及任意分数的舍入误差的影响(例如,加1/3),唯一能说明这一点的方法是在比较双精度和/或小数时,将某个公差内的任何值视为"相等"。
  • 如果使用双数更合适,我可以提出什么样的论点(除了我已经提出的论点)来说服我的团队不要将所有内容都改为小数?

  • 当您需要完美的准确度作为基数10(财务数据、等级)时,使用decimal

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

    由于您似乎只存储各种测量值(无论如何都有一定的精度),因此如果您需要超过7位的精度,float将是逻辑选择(或double)。

    Is using decimals actually solving an issue that doubles could not?

    不是真的-数据只会和生成数据所用的测量值一样精确。你真的能说一个测量的量是123.4567克吗?用来测量它的设备有那么高的精度吗?

    为了处理"舍入误差",我会说,你不能真的说1234.5克的测量值是否正好是中间值——它也可能是1234.49克,这无论如何都会舍入。

    你需要决定的是"什么样的精度水平是可以接受的",并且作为最后一步,总是四舍五入到那个精度。不要将数据或中间计算四舍五入。

    If it is more appropriate to use doubles, what arguments could I make (other than what I have already made) could convince my team to not change everything to decimals?

    除了花在切换上的时间,你真正要牺牲的是速度。唯一知道速度多少的方法是尝试两种方法并测量差异。


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

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

    1
    2
    3
    4
    5
    INT get_index(DOUBLE VALUE) {
        IF (VALUE < 0 || VALUE > 1.00)
            RETURN -1;
        RETURN VALUE / 0.10;
    }

    我确定了:

    1
    2
    3
    4
    5
    INT get_index(DOUBLE VALUE) {
        IF (VALUE < 0 || VALUE > 1.00)
            RETURN -1;
        RETURN (VALUE * 100000000) / (0.10 * 100000000);
    }