当将 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不一致地显示机器精度错误?
谢谢。
问题比这简单。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 位十进制精度的结果,但根据参数,结果可能会略高于或略低于正确答案。