SQL 服务器的浮点数小于 2.23E-308(双精度数的最小值)

SQL Server has float number less than 2.23E-308 (minimum of double precision number)

我们正在使用 SQL Server 2014 来存储来自 C 库的结果。最近我们发现有一些像 1.39202924295074E-309 这样的值存储在定义为浮点数的列中。

这很奇怪,因为基于 MSDN,浮动范围是

 -1.79E+308 to -2.23E-308, 0 and 2.23E-308 to 1.79E+308

默认情况下与我找到的任何文献一致。

所以问题是为什么我们得到的值小于允许的最小值?

table 的设计类似于

CREATE TABLE [dbo].[CLibDataResult](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Result] [float] NOT NULL
)

虽然看起来很奇怪,但您提供的值在范围内。如果您使用 .NET,您可以使用以下代码对其进行测试:

var d = double.Parse("1.39202924295074E-309");
var min = double.Parse("-1.79E+308");            
Console.WriteLine(d > min);  // returns true

我认为 MSDN 文本令人困惑。

在互联网上进行了一些挖掘之后,我想我可以回答我的问题。其中一个参考文献是 page and this page.

这里有两个概念,一个是最小正正规数和最小正subnormal数。 MSDN 页面列出了基于最小正数 normal 的范围。但是根据 IEEE 754,最小正次正规数是双扩展格式中可表示的最小正数。

这里有一个作弊 sheet 这些数字的双精度,

--------------------------------------------------------------
| max normal number             |   1.7976931348623157e+308  |
--------------------------------------------------------------
| min positive normal number    | 2.2250738585072014e-308    |
--------------------------------------------------------------                                           
| max subnormal number          |   2.2250738585072009e-308  |
--------------------------------------------------------------                                           
| min positive subnormal number |   4.9406564584124654e-324  |
--------------------------------------------------------------

总之,可表示的最小值是 4.9406564584124654e-324,而 1.39E-309 比它大。所以 SQL 服务器符合 IEEE 双精度标准。

如果你从这个开始

update [CLibDataResult] set result = power(cast(10.000 as float),-300);

 INSERT [CLibDataResult] VALUES(power(cast(10.000 as float),-300));

然后重复运行

update [CLibDataResult] set result = result / 10;
select * from [CLibDataResult];

你可以看到这个值变小了,然后在 e-308 左右,它的精度似乎崩溃了,因为可用的数字越来越少,最后它消失为零