【问题标题】:Rounding issue with SQL Server and REAL datatypeSQL Server 和 REAL 数据类型的舍入问题
【发布时间】:2015-10-16 21:08:36
【问题描述】:

我在 SQL Server 2008 中四舍五入时看到一些奇怪的行为。鉴于以下代码:

DECLARE @Value REAL
SELECT @Value = .35
SELECT ROUND(@Value, 1)

我希望该值为 0.4,但它输出 0.3。我必须假设这是因为存储的值实际上小于 0.35,类似于 0.34999999999999。是这种情况,还是我做错了什么?有没有办法确保其行为符合预期,至少从可见值来看?

【问题讨论】:

  • 如果@Value 的类型是DECIMAL(10,2),你会得到什么?请记住,REAL 是一种近似数据类型,这意味着它可能确实将 .35 存储为 .34999999999999 或类似的东西。
  • 使用 DECIMAL(10,2) 可以得到预期的结果。不幸的是,我的数据库已经为此使用了 REAL。也许我需要考虑转换。
  • 是的,我建议转换。 REALFLOAT 不是您应该使用的数据类型,如果您期望逻辑(例如,比大多数科学教给您的更近似)四舍五入。

标签: sql-server rounding


【解决方案1】:

当您使用 REAL 和 FLOAT 之类的浮点值(相同)时,SQL Server ROUND() 函数遵循 IEEE 标准 754 并使用“向上取整”算法。

但这对于不同的浮点值意味着不同的东西。一些“.5”值最终被存储为“.49999999999”的近似值,其他的为“.500000001”等。它会四舍五入实际存储的值,而不是你一开始给它的值。

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

如果精确的十进制数学对您很重要,请使用 DECIMAL,而不是 FLOAT 或 REAL。

【讨论】:

    【解决方案2】:

    数据被存储为真实数据太糟糕了,但并不是所有的希望都落空了。在四舍五入之前将 REAL 转换为 DECIMAL(10,2)。这样,0.3499999999999(或存储的任何不准确值)将四舍五入为 0.35,然后将其四舍五入为 0.4。如果您希望结果显示为0.4,您甚至可以将其转换为 DECIMAL(10,1):

    DECLARE @Value REAL
    SELECT @Value = .35
    SELECT CONVERT(DECIMAL(10,1), ROUND(CONVERT(DECIMAL(10,2), @Value), 1))
    

    【讨论】:

    • 这显然有效!赞!我想知道这些转换有多快。如果我只是用这个计算来代替回合,我想知道它会对我造成多大的伤害。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-04
    • 2018-02-07
    • 1970-01-01
    相关资源
    最近更新 更多