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,如果您想要精确,则需要将数据存储在字符串中。
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,如果您想要精确,则需要将数据存储在字符串中。