Number (realToFrac) 在 Aeson 中创建尾随数字过多的浮点数

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

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

下面的代码使用有问题的表达式来 JSON-编码 Float 值:

data Value =
    VInt Int
  | VFloat Float
  deriving Show

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

这将输出 JSON,其值类似于 10.4000000000000003552713678800500929355621337890625

为什么 Number (realToFrac 10.4) 后面有这么多数字,如何解决这个问题?

由于种种原因,目前还没有完美的解决方案。您可能喜欢 fromFloatDigits——10.4 会更好,但其他数字会更差。

https://github.com/haskell/aeson/issues/546 详细讨论了这个一般性问题。讨论并没有真正引向任何地方。如果说有什么值得借鉴的话,那就是 JSON 世界中的数字基本上总是 broken/ambiguous,如果您想要精确,则需要将数据存储在字符串中。