SQL Server - 将 LOG 结果截断为整数时出现不一致、隐藏的机器精度错误

Ela*_*tor 4 sql-server

当将 1000 的 log base 10 转换为整数时,我注意到 SQL Server(至少 2008R2)中有一些奇怪的舍入行为。答案显然是确切的值 3,但一定有一些小数 SQL 服务器隐藏在输出中:

SELECT LOG(1000, 10)--returns 3 with no visible decimals
SELECT CONVERT(INT, LOG(1000, 10))--returns 2
Run Code Online (Sandbox Code Playgroud)

当添加到LOG转换前的结果时,我对最小 epsilon 进行逆向工程以获得正确的值,大约为:

SELECT CONVERT(INT, LOG(1000, 10)+0.0000000000000002220446049250313)
SELECT CONVERT(INT, LOG(1000, 10)+0.0000000000000002220446049250312)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

看来我可以整天继续使这个值更精确。

这似乎只在 1000 的情况下是必要的,因为我在不使用任何 epsilon 项的情况下获得了 1、10、100 和 10000 及更大的正确整数值。

错误项似乎是泰勒级数的尾部扩展了 16 项(根据本页),但是当我在 10000 及更大的情况下尝试此操作时,为什么 SQL Server 突然按预期运行(没有隐藏的机器精度错误) ?

为什么 SQL Server不一致地显示机器精度错误?

谢谢。

Dav*_*oft 6

问题比这简单。LOG 输出一个浮点数,在将浮点值转换为 int 而不是截断时,您应该始终ROUND

你正在做的类似于:

select cast(0.99999999999999999999999999999999999 as int)
Run Code Online (Sandbox Code Playgroud)

LOG(1000,10)的结果不是3,可以看到

select convert(varchar(200),LOG(1000, 10), 3)
Run Code Online (Sandbox Code Playgroud)

最接近

   2.9999999999999996e+000
Run Code Online (Sandbox Code Playgroud)

(尽管在内部有效数存储在 base-2 中)。

这种行为没有任何不一致之处。LOG 是基于收敛到对数的级数展开的估计,结果以有限的精度返回。

LOG 函数旨在返回精确到 15 位十进制精度的结果,但根据参数,结果可能会略高于或略低于正确答案。