在将 1000 的以 10 为底的对数转换为整数时,我注意到 SQL Server(至少 2008R2)中存在一些奇怪的舍入行为。答案显然是精确值 3,但 SQL 服务器在输出中隐藏了一些小数:
SELECT LOG(1000, 10)--returns 3 with no visible decimals
SELECT CONVERT(INT, LOG(1000, 10))--returns 2
我对最小 epsilon 进行了逆向工程,以便在将其添加到LOG
转换前的结果中时获得正确的值,大致如下:
SELECT CONVERT(INT, LOG(1000, 10)+0.0000000000000002220446049250313)
SELECT CONVERT(INT, LOG(1000, 10)+0.0000000000000002220446049250312)
看来我可以整天继续使这个值更精确。
这似乎仅对于 1000 的情况是必要的,因为我在不使用任何 epsilon 项的情况下获得了 1、10、100 和 10000 以及更大的正确整数值。
错误项似乎是泰勒级数的尾部扩展了 16 个项(根据此页面),但是当我尝试针对 10000 和更大的情况时,为什么 SQL Server 突然按预期运行(没有隐藏的机器精度错误) ?
为什么 SQL Server不一致地显示机器精度错误?
谢谢。
问题比这简单。LOG 输出一个浮点数,在将浮点值转换为 int 而不是截断时,您应该始终使用ROUND 。
你在做什么类似于:
LOG(1000,10)的结果不是3,可以看到
最接近
(尽管在内部有效数字存储在 base-2 中)。
这种行为没有什么不一致的。LOG 是基于收敛于对数的级数展开的估计,返回的结果精度有限。
LOG 函数旨在返回精确到 15 位小数精度的结果,但根据参数,结果可能略高于或略低于正确答案。
为什么这可能是 MSSQL 的“一致行为”,我认为这是违反直觉的。
我不敢相信我会这么说,但看起来 SQL Server 将浮点数作为更高精度的小数处理,直到您完成计算,然后它才将浮点数转换为您的变量(或您的选择) .
MSDN 说
Log()
返回一个浮点数。我观察到的是浮点数被处理为更高精度的十进制值: