5

根据MSDN,REAL 值的范围是 - 3.40E + 38 到 -1.18E - 38、0 和 1.18E - 38 到 3.40E + 38。但是,我的表中有很多超出该范围的值。

以下查询返回许多非常小的值,而没有非常大的值:

SELECT  MyColumn ,
        *
FROM    data.MyTable
WHERE   MyColumn <> 0
        AND ( MyColumn < CONVERT(REAL, 1.18E-38)
              OR MyColumn > CONVERT(REAL, 3.40E+38)
            )
        AND ( MyColumn < CONVERT(REAL, -3.40E+38)
              OR MyColumn > CONVERT(REAL, -1.18E-38)
            ) 

很容易显示这些值如何最终出现在表中。我不能直接插入它们:

CREATE TABLE a(r REAL NULL);
GO
INSERT INTO a(r) VALUES(4.330473E-39);
GO
SELECT r FROM a
GO
DROP TABLE a;

----
0.0

但我可以划分两列并获取和超出范围值:

CREATE TABLE a
  (
    r1 REAL NULL ,
    r2 REAL NULL ,
    r3 REAL NULL
  ) ;
GO
INSERT  INTO a
        ( r1, r2 )
VALUES  ( 4.330473E-38, 1000 ) ;
GO
UPDATE  a
SET     r3 = r1 / r2 ;
SELECT  r1 ,
        r2 ,
        r3
FROM    a

r1            r2            r3
------------- ------------- -------------
4.330473E-38  1000          4.330433E-41

所以我猜 MSDN 给出了错误的有效数据范围,对吗?我错过了什么吗?

有几个人建议这是一个错误。

这种行为的哪一部分到底是一个错误。是吗:

  1. MSDN 中记录并在 DBCC 中使用的错误常量,以及向下舍入的错误阈值。
  2. 更新能够保存错误的值
4

2 回答 2

7

联机丛书仅记录单精度和双精度浮点数的正常范围。IEEE 754规则还指定了比最小非零正常值更接近零的浮点数,这些浮点数被称为非规范化、非规范化和次规范化数字。从最后一个链接:

非正规数保证浮点数的加法和减法永远不会下溢;两个相邻的浮点数总是有一个可表示的非零差。如果没有逐渐下溢,即使值不相等,减法 a−b 也会下溢并产生零。反过来,这会导致除以零错误,而使用逐渐下溢时不会发生这种错误。

SQL Server 遵循发布示例中的单精度浮点计算规则。该错误可能是 DBCC 仅检查正常值,并在遇到存储的非正常值时抛出不正确的错误消息。

生成非规范单精度值的示例:

DECLARE
    @v1 real = 14e-39,
    @v2 real = 1e+07;

-- 1.4013e-045
SELECT @v1 / @v2;

显示存储的float异常通过 DBCC 检查的示例:

CREATE TABLE dbo.b (v1 float PRIMARY KEY);
INSERT b VALUES (POWER(2e0, -1075));
SELECT v1 FROM b; -- 4.94065645841247E-324
DBCC CHECKTABLE(b) WITH DATA_PURITY; -- No errors or warnings
DROP TABLE dbo.b;
于 2012-07-03T03:54:21.767 回答
0

这是 SQL Server 中的一个错误。您发布的最后一个脚本是一个很好的复制品。在最后添加一行:

DBCC CHECKDB WITH data_purity

这失败了:

消息 2570,级别 16,状态 3,第 1 行页面 (1:313),对象 ID 357576312 中的插槽 0,索引 ID 0,分区 ID 1801439851932155904,分配单元 ID 2017612634169999360(类型“行内数据”)。列“r3”的值超出了数据类型“real”的范围。将列更新为合法值。

这证明它是一个错误。我建议您使用Microsoft Connect for SQL Server提交错误。

于 2012-07-02T17:51:22.063 回答