Number (realToFrac) 在 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

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

data Value =
    VInt Int
  | VFloat Float
  deriving Show

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

这将输出带有 10.4000000000000003552713678800500929355621337890625 之类的值的 JSON。

为什么会有这么多带有 Number (realToFrac 10.4) 的尾随数字以及如何解决这个问题?

解决方法

由于种种原因,没有完美的解决方案。您可能喜欢 fromFloatDigits -- 使用 10.4 会更好,但使用其他数字会更糟。

,

https://github.com/haskell/aeson/issues/546 中详细讨论了这个一般性问题。讨论并没有真正导致任何结果。如果说有什么要注意的,那就是在 JSON 世界中,数字基本上总是坏的/模棱两可的,如果您想精确,则需要将数据存储在字符串中。