Search code examples
jsonhaskellfloating-pointaeson

Number (realToFrac) creates float with too many trailing digits in Aeson


A few experiments with Data.Aeson.Types.Internal.Number

import Data.Aeson

10.4
-- 10.4

realToFrac 10.4
-- 10.4

Number (realToFrac 10.4)   -- <-- the problematic expression
-- Number 10.4000000000000003552713678800500929355621337890625

Number 10.4
-- Number 10.4

The code below uses the problematic expression in order to JSON-encode a Float value:

data Value =
    VInt Int
  | VFloat Float
  deriving Show

instance ToJSON Value where
    toJSON (VInt n)   = Number (fromIntegral n)
    toJSON (VFloat f) = Number (realToFrac f)

Which will output JSON with values like 10.4000000000000003552713678800500929355621337890625.

How comes there are so many trailing digits with Number (realToFrac 10.4) and how to address this problem?


Solution

  • For various reasons, there is no perfect solution. You might like fromFloatDigits -- it will do better with 10.4, but worse with some other numbers.