Haskell: Convert Double to Int
Solution 1
Not use -1
(you can but) use Maybe
(or throw exception if you don't want control i.e. is controlled in other way)
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
on the other hand, input type can be different than output type (with the same body code)
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
Note: since we are using Maybe
(to avoid a bad -1
response) you must control flow control in your code like
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!"
finally, if you are working with bits, you can get used bits to store certain number using 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
Solution 2
To people that lands at this page snared by its title "Convert Double to Int". There are three functions in the Haskell Prelude that help: round, floor and ceiling.
Here is an example:
Prelude> let myFloat = 3.1415 :: Double
Prelude> let y = round myFloat :: Int
Prelude> y
3
Prelude> :type y
y :: Int
LeO
Updated on June 04, 2022Comments
-
LeO almost 2 years
I want to compute "which power of a number do I have to use" from a fixed base, e.g. 2.
I want to find the next (integer) power of a number, e.g.
2 ^ 3 = 8 ==> get2Power 8 ==> 3
.This is simple, but
get2Power 10 ==> 4
since2^3=8
as the lower bound and2^4=16
as the upper bound I want to return the upper one,4
.With simple math I know that I can calculate the power with some logarithm function, i.e.
log(x) / log(2)
which results in a Double. But I want to have the nextInteger
.My approach looks like
get2Power :: Integer -> Integer get2Power x | x <= 0 = -1 | otherwise = round (log(x) / log (2))
which fails cause there is missing some conversion between the Types. The error message is not helpful to get an idea of what I'm missing.
Could anybody give me a helping hand about how to transform the Double result into an Integer/int?
-
LeO about 10 yearsthx, BUTTTT .... The approach with the usedBits sounds great, but I am not interested for this sample in recursive solution (although the code is nice ;) ). The code for the get2Power does not solve problem with
Integer
conversion, namely2^(get2Power 10)
does not work, i.e. I cannot use the result of the get2Power for further computation. (Perhaps not clear from the beginning, but...) -
josejuan about 10 years@LeO with your original function you can do
2^(get2Power (-5))
, but is not correct!, you must learn aboutMaybe
. I wrote a usage example :) -
josejuan about 10 years"...I am not interested ... in recursive solution...", is not recursive! :)
-
leftaroundabout about 10 yearsWhile
Maybe
is certainly a good thing to know about and quite reasonable here, I wouldn't say you must use it. For maths functions where the valid range is obvious it's generally considered ok (at least it was when the Haskell standard modules where written) to leave them as partial functions. Certainly,-1
is not an acceptable error case, but throwing an exception would be ok. -
LeO about 10 years
Maybe
is interesting - maybe ;) The comment from josejuan is interesting, cause in my EclipseFP-environment I get for the function defined aboveNo instance for (Fractional Integer) rising from a use of '/' Possible fix: add an instance declaration for (Fractional Integer ...
which means I cannot compile it. Seems like myreal
issue is somewhere else? Hints??? -
Jorgen over 6 yearsand truncate :: Integral b => a -> b