Haskell:将Double转换为Int

时间:2014-01-28 08:01:02

标签: haskell type-conversion

我想从固定基数计算“我必须使用的数字的哪个幂”,例如2.

我想找到一个数字的下一个(整数)幂,例如2 ^ 3 = 8 ==> get2Power 8 ==> 3

这很简单,但get2Power 10 ==> 4因为2^3=8作为下限而2^4=16作为上限我想返回上限4

通过简单的数学运算,我知道我可以用一些对数函数来计算功率,即log(x) / log(2),这会产生一个双精度。但我想拥有下一个Integer

我的方法看起来像

get2Power :: Integer -> Integer
get2Power x 
  | x <= 0 = -1
  | otherwise = round (log(x) / log (2))     

失败导致类型之间缺少某些转换。错误消息无助于了解我所缺少的内容。

有人可以帮我解决如何将Double结果转换为Integer / int的问题吗?

2 个答案:

答案 0 :(得分:16)

对于登陆此页面的人来说,其标题是“将Double转换为Int”。 Haskell Prelude中有三个函数可以提供帮助:roundfloorceiling

以下是一个例子:

Prelude> let myFloat = 3.1415 :: Double
Prelude> let y = round myFloat :: Int
Prelude> y
3
Prelude> :type y
y :: Int

答案 1 :(得分:3)

不使用-1(你可以但是)使用Maybe(如果你不想要控制,则抛出异常,即以其他方式控制)

get2Power :: Integral a => a -> Maybe a
get2Power x | x <= 0    = Nothing
            | otherwise = Just (ceiling (log (fromIntegral x) / log 2))

Prelude> get2Power (256 :: Int)
Just 8
it :: Maybe Integer

另一方面,输入类型可以与输出类型(具有相同的主体代码)不同

get2Power :: (Integral a, Integral b) => a -> Maybe b
              ^^^^^^^^^^^^^^^^^^^^^^
              (note how to force args to be Integral: Int, Integer, ...)

get2Power x | x <= 0    = Nothing
            | otherwise = Just (ceiling (log (fromIntegral x) / log 2))

Prelude> get2Power (2^123 :: Integer) :: Maybe Int
                          ^^^^^^^^^^^          ^^^
                          (note here how to force certain type)

Just 123
it :: Maybe Int

注意:,因为我们正在使用Maybe(以避免错误的-1响应)您必须控制代码中的流量控制,例如

main = do
  putStrLn "Enter a number:"
  n <- readLn
  case get2Power n of
    Just k  -> putStrLn $ "2^" ++ show k ++ " is above " ++ show n
    Nothing -> putStrLn "Negative numbers not allowed!"

最后,如果您正在使用位,您可以使用Data.Bits来获取使用的位来存储某个数字

usedBits :: Bits a => a -> Int
usedBits n = length $ dropWhile not bs
             where bs = [testBit n b | b <- reverse [0..bitSize n - 1]]

Prelude Data.Bits> usedBits (256 :: Int)
9
it :: Int