并在右侧使用它,我如何将解决方案追溯到较低的数字?
递归。由于计算下限更容易,我们使用以下事实
ceiling (log_2 n) == floor (log_2 (2*n-1))
很容易看出。然后为了找到以底为底b
的对数,我们计算以底为底的对数b²
并进行调整:
log2 :: Int -> Int
log2 1 = 0
log2 2 = 1
log2 n
| n < 1 = error "Argument of logarithm must be positive"
| otherwise = fst $ doLog 2 1
where
m = 2*n-1
doLog base acc
| base*acc > m = (0, acc)
| otherwise = case doLog (base*base) acc of
(e, a) | base*a > m -> (2*e, a)
| otherwise -> (2*e+1,a*base)
需要更多步骤的更简单算法是简单地迭代,在每一步中乘以 2,然后计数,直到达到或超过参数值:
log2 :: Int -> Int
log2 n
| n < 1 = error "agument of logarithm must be positive"
| otherwise = go 0 1
where
go exponent prod
| prod < n = go (exponent + 1) (2*prod)
| otherwise = exponent