我试图找到一个可靠、有效的表达式来计算写一个正整数需要多少个十进制数字。
在数学上,整数中的十进制位数n
是1 + floor(log(n))
,其中 log 是常用对数(以 10 为底)。
有多种使用内置函数构造等效表达式的方法,但其中一些会给出错误的结果。有人可以解释为什么吗?
这是一个例子。
计算常用对数的最简单方法是使用LOG10
函数。
如果您希望所有对数都使用一个函数,则可以使用该LOG
函数并使用第二个参数指定以 10 为底的函数。
在 2012 年之前,SQL Server 的LOG
函数将仅计算自然对数(基数 e=2.71828...)。您可以通过将数字的自然对数除以数字的自然对数来计算对数到数字的任意底数。
以下查询为一些示例值计算所有三个表达式:
SELECT
Number,
LOG(Number, 10) AS LogAB,
LOG10(Number) AS LogTen,
LOG(Number) / LOG(10) AS LogOverLog
FROM (
VALUES (999), (1000), (1001)
) AS Tally (Number);
Run Code Online (Sandbox Code Playgroud)
输出:
Number LogAB LogTen LogOverLog
----------- ---------------------- ---------------------- ----------------------
999 2.99956548822598 2.99956548822598 2.99956548822598
1000 3 3 3
1001 3.00043407747932 3.00043407747932 3.00043407747932
Run Code Online (Sandbox Code Playgroud)
我选择了值 999、1000 和 1001,因为 1000 是数字数量增加的点。999有3位数字,1000有4位数字。
所有三个表达式的值明显相同,并且看起来是正确的。
让我们继续到地板步骤。
您可以使用如下查询来查看上一个示例中的每个日志:
SELECT
Number,
FLOOR(LOG(Number, 10)) AS FloorLogAB,
FLOOR(LOG10(Number)) AS FloorLogTen,
FLOOR(LOG(Number) / LOG(10)) AS FloorLogOverLog
FROM (
VALUES (999), (1000), (1001)
) AS Tally (Number);
Run Code Online (Sandbox Code Playgroud)
输出:
Number FloorLogAB FloorLogTen FloorLogOverLog
----------- ---------------------- ---------------------- ----------------------
999 2 2 2
1000 2 3 2
1001 3 3 3
Run Code Online (Sandbox Code Playgroud)
999 和 1001 的每个表达式的值相等且正确。如果我们给每个值加 1,我们将在 999 中计数 3 位,在 1001 中计数为 4 位。
1000 的值不一样!如果我们给每个值加 1,如果我们使用该LOG10
函数,我们将在 1000 中计数为 4 位,如果我们LOG
以任何形式使用该函数,则计数为 3 位。
这里有矛盾!
含义很清楚:使用该LOG
函数会给我一些值的错误计数,所以我应该使用该LOG10
函数。
但是每个日志表达式本身的值都是相同且正确的。为什么 floor 函数会根据其输入产生不同的值?
SELECT
Number,
CAST(LOG(Number, 10) AS VARBINARY) AS LogAB,
CAST(LOG10(Number) AS VARBINARY) AS LogTen,
CAST(LOG(Number) / LOG(10) AS VARBINARY) AS LogOverLog
FROM (
VALUES (1000)
) AS Tally (Number);
Run Code Online (Sandbox Code Playgroud)
退货
Number LogAB LogTen LogOverLog
----------- ----------------------- ----------------------- ----------------------
1000 0x4007FFFFFFFFFFFF 0x4008000000000000 0x4007FFFFFFFFFFFF
Run Code Online (Sandbox Code Playgroud)
0x4008000000000000
是正好3。
0x4007FFFFFFFFFFFF
是2.99999999999999955591079014994。
如果您正在寻找一个有效的表达式,那么CASE
具有 10 种不同情况的表达式实际上会比计算对数消耗更少的 CPU(或者可能您可以使用嵌套的 case 表达式来进行三元搜索)
归档时间: |
|
查看次数: |
331 次 |
最近记录: |