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 左右,它的精度似乎崩溃了,因为可用的数字越来越少,最后它消失为零
我们正在使用 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 左右,它的精度似乎崩溃了,因为可用的数字越来越少,最后它消失为零