Eben Kadile
Eben Kadile

Reputation: 779

Best way to implement floor and fract for floating point numbers in Haskell?

floor in Haskell is defined only for the RealFrac typeclass. I don't really know much about this typeclass and the rest of my code only uses floating point numbers.

I can't find any function for casting a Float to an Int. If there were then floor would be equivalent to fromIntegral (fromFloating x) and fract would be defined as

fract x = x - floor x

However, as I said, I haven't found any function that does anything like what I want fromFloating to do. So this is the only way I could think of for implementing fract:

fract x 
    | x < 0 = 1 - fract (abs x)
    | x < 1 = x
    | otherwise = fract (x - 1)

and then of course floor x would be x - fract x. The algorithm above, however, is O(n) and it's going to drastically slow things down, so I'm hoping there's a way to do this that is constant time.

Upvotes: 1

Views: 683

Answers (1)

Daniel Martin
Daniel Martin

Reputation: 23548

As the comments say, floor is already implemented for floating point numbers, and frac is straightforward; this code compiles:

aDouble :: Double
aDouble = -5.675

aFloat :: Float
aFloat = 10.675

frac :: RealFrac a => a -> a
frac x = x - fromIntegral (floor x :: Integer)

main :: IO ()
main = do
  putStrLn "aDouble is"
  print aDouble
  putStrLn "frac(aDouble) is"
  print (frac aDouble)
  putStrLn "aFloat is"
  print aFloat
  putStrLn "frac(aFloat) is"
  print (frac aFloat)

and produces:

$ runhaskell /tmp/a.hs
aDouble is
-5.675
frac(aDouble) is
0.3250000000000002
aFloat is
10.675
frac(aFloat) is
0.6750002

Upvotes: 1

Related Questions