Floating point numbers, precision and parsec

Consider the following code:

import Text.Parsec
import Text.Parsec.Language
import Text.Parsec.String
import qualified Text.Parsec.Token as Token

float :: Parser Double
float = Token.float (Token.makeTokenParser emptyDef)

myTest :: String -> Either ParseError Double
myTest = parse float ""

Now, thanks to QuickCheck, I know the magic number (I aligned the result for convenience):

λ> myTest "4.23808622486133"
Right      4.2380862248613305

Some floating-point numbers may not be accurately represented in memory; some operations easily introduce “fluctuations” into floating-point numbers. We all know that. However, the reason for this parsing problem seems different.

, ... . , , ( Parsec). , 9.2, , , (, - "" ). 4.23808622486133?


, , , 4.23808622486133 - 4.2380862248613305:

a1 :: Double
a1 = 9.2000000000000003

a2 :: Double
a2 = 9.200000000000001

b1 :: Double
b1 = 4.23808622486133

b2 :: Double
b2 = 4.2380862248613305

:

λ> a1 == a2
True
λ> b1 == b2
False
+4
2

Parsec. , Megaparsec, Parsec, , ..

, ​​:

λ> parseTest float "4.23808622486133"
4.23808622486133
λ> parseTest float "4.2380862248613305"
4.2380862248613305

: Megaparsec.

0

Parsec Double,

foldr (\d acc -> read [d] + acc / 10) 0 "423808622486133" :: Double

, ,

423808622486133 / 100000000000000 :: Double

, ​​Parsec.

+3

Source: https://habr.com/ru/post/1584232/


All Articles