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 a magic number (I have aligned result for convenience):
λ> myTest "4.23808622486133"
Right 4.2380862248613305
Some floating point numbers cannot be exactly represented in memory, some operations easily introduce «fluctuations» into floating point numbers. We all know that. However, cause of this parsing problem seems to be different.
A few words about tests that helped me discover this… feature. Put simply,
in these tests floating point value is generated, printed, and parsed back
(with Parsec). For example, number 9.2
is known to be impossible to
represent as floating
point value,
however it passes the tests (obviously because of «smart» printing
function). Why does 4.23808622486133
fail?
For those who believe that these numbers are the same and 4.23808622486133
is just shortest unambiguous representation of 4.2380862248613305
:
a1 :: Double
a1 = 9.2000000000000003
a2 :: Double
a2 = 9.200000000000001
b1 :: Double
b1 = 4.23808622486133
b2 :: Double
b2 = 4.2380862248613305
Now:
λ> a1 == a2
True
λ> b1 == b2
False
This is still not fixed in Parsec. If this exact problem breaks your day, take a look at Megaparsec, which is a fork of Parsec that fixes many bugs and conceptual flaws, improves quality of error messages and more.
As you can see this problem is fixed there:
λ> parseTest float "4.23808622486133"
4.23808622486133
λ> parseTest float "4.2380862248613305"
4.2380862248613305
Disclosure: I'm one of the authors of Megaparsec.