Alex Chapman
Alex Chapman

Reputation: 33

What is the right way to convert from Double to Fixed in Haskell?

I have some code that uses Centi for its currency type. It receives Doubles from an Excel spreadsheet using the xlsx package. I want to convert these Doubles into Centis correctly. I have tried using realToFrac, and for the most part it works, but occasionally it's out by a cent:

λ realToFrac (-1372.92 :: Double) :: Centi
-1372.93

I can guess that the problem is in the binary representation of that decimal number not being exact, and that I shouldn't be using Double to represent currency in the first place, but I don't have control of that part. So what is a fail-safe way of doing the conversion?

Upvotes: 3

Views: 369

Answers (1)

Li-yao Xia
Li-yao Xia

Reputation: 33399

Maybe not the best way but one is to round to the closest integer after adjusting for the desired precision:

floatToCenti :: Double -> Centi
floatToCenti = floatToFixed

floatToFixed :: HasResolution a => Double -> Fixed a
floatToFixed x = y where
  y = MkFixed (round (fromInteger (resolution y) * x))
  -- reusing y as the dummy argument of resolution

Upvotes: 2

Related Questions