首页 > 解决方案 > 更适合阅读 Haskell 中的科学记数法

问题描述

Haskellread对浮点数有点过于严格:

$ ghci
GHCi, version 8.2.2: http://www.haskell.org/ghc/  :? for help
Prelude> read "-1E34" :: Double
-1.0e34
Prelude> read "-1.E34" :: Double
*** Exception: Prelude.read: no parse
Prelude>

是否有接受第二种形式的 read 版本?这在物理科学中很常见。例如,Fortran 读取和写入此类表单。

Haskell 不支持的另一个例子是“0.1”的“.1”。这个更常见。我只是不想转换输入的 ascii 文件。. . .

标签: haskellscientific-notation

解决方案


这是一个使用megaparsec执行此操作的自定义解析器。

import Text.Megaparsec
import Text.Megaparsec.Char

realLiteral :: (MonadParsec e s m, Token s ~ Char) => m Double
realLiteral = mkFloat <$> sign <*> intgPart <*> fracPart <*> exponent
 where mkFloat sgn itg frc expn
           = fromIntegral sgn * (fromIntegral itg + frc) * 10^^expn
       sign = (-1) <$ char '-'
           <|> 1   <$ char '+'
           <|> pure 1
       intgPart = read . ('0':) <$> many digitChar
       fracPart = char '.' *> (toFrc<$>many digitChar)
               <|> pure 0
        where toFrc "" = 0
              toFrc digits = read digits / 10^length digits
       exponent = oneOf "eEdD" *> ((*) <$> sign <*> (read<$>some digitChar))
               <|> pure 0
[1 of 1] 编译 Main(wtmpf-file5764.hs,解释)
好的,已加载 1 个模块。
*Main> parseMaybe realLiteral "1"
仅 1.0
*Main> parseMaybe realLiteral "-3"
只是(-3.0)
*Main> parseMaybe realLiteral "-9e+2"
只是 (-900.0)
*Main> parseMaybe realLiteral ".3e+9"
只需 3.0e8
*Main> parseMaybe realLiteral "-1.E34"
只是(-1.0000000000000001e34)
*Main> parseMaybe realLiteral "-1.673986e-40"
只是(-1.6739859999999999e-40)
*Main> parseMaybe realLiteral "-3.E+16"
只是(-3.0e16)

推荐阅读