我正在尝试使用长度等于truncate (log10(x)+1)
的事实来计算Haskell中Integer的长度。
使用我创建的整数:
len :: Integer -> Integer
len i = toInteger (truncate (logBase 10 (fromIntegral i)) + 1)
不幸的是,并非所有数字都能获得正确的长度。我尝试了几个不同的案例,发现:
logBase 10 10 = 1.0
logBase 10 100 = 2.0
logBase 10 1000 = 2.9999..6
logBase 10 10000 = 4.0
logBase 10 100000 = 5.0
logBase 10 1000000 = 5.9999999
logBase 10 1000
没有返回3.0的原因吗?如何在基数10中获得1000的正确日志值?
答案 0 :(得分:4)
GHC模块中有一个整数日志库函数,其类型为Integer -> Integer -> Int#
。
使用示例:
{-# LANGUAGE MagicHash #-}
import Control.Monad
import GHC.Integer.Logarithms ( integerLogBase# )
import GHC.Exts (Int(..))
main = do
forM_ [(1::Int)..20] $ \n -> do
let a = 10^n-1
la = I# (integerLogBase# 10 a)
b = 10^n
lb = I# (integerLogBase# 10 b)
putStrLn $ show a ++ " -> " ++ show la
putStrLn $ show b ++ " -> " ++ show lb
输出:
9 -> 0
10 -> 1
99 -> 1
100 -> 2
999 -> 2
1000 -> 3
9999 -> 3
10000 -> 4
99999 -> 4
100000 -> 5
999999 -> 5
1000000 -> 6
9999999 -> 6
...
9999999999999999999 -> 18
10000000000000000000 -> 19
99999999999999999999 -> 19
100000000000000000000 -> 20
答案 1 :(得分:1)
如果您不需要Double
浮动精度,请改用Float
类型,这似乎很好。例如logBase 10 (1000 :: Float)
将返回3.0
或功能logBase 10 . (fromInteger :: Integer -> Float) $ 1000
也会这样做。
根据您的代码toInteger
似乎是多余的,因为truncate :: (Integral b, RealFrac a) => a -> b
已经完成了这项工作。所以可能只是喜欢
len :: Integer -> Integer
len = (+1) . truncate . logBase 10 . (fromIntegral :: Integer -> Float)
这将在9999987之前正常工作。
答案 2 :(得分:0)
你不能就去
amountOfDigits = length . show
(如果您只对传统的以10为底的数字感兴趣)