@@ -18,6 +18,7 @@ module Data.Text.Lex
18 , hexadecimal
18 , hexadecimal
20 , rational
20 , rational
23import Control.Monad (liftM)
24import Control.Monad (liftM)
@@ -119,3 +120,30 @@ rational = runP $ do
119 else fromRational $ if power == 0
120 else fromRational $ if power == 0
120 then real % 1 + fraction % (10 ^ fracDigits)
121 then real % 1 + fraction % (10 ^ fracDigits)
121 else (real % 1 + fraction % (10 ^ fracDigits)) * (10 ^^ power)
122 else (real % 1 + fraction % (10 ^ fracDigits)) * (10 ^^ power)
124+-- | Read a rational number. This function is about ten times faster
125+-- than 'rational', but is slightly less accurate.
127+-- The 'Double' type supports about 16 decimal places of accuracy.
128+-- For 94.2% of numbers, this function and 'rational' give identical
129+-- results, but for the remaining 5.8%, this function loses precision
130+-- around the 15th decimal place. For 0.001% of numbers, this
131+-- function will lose precision at the 13th or 14th decimal place.
132+double :: Lexer Double
134+ real <- signa (P decimal) :: Parser Integer
135+ (fraction,fracDigits) <- perhaps (0,0) $ do
137+ digits <- P $ \t -> Right (T.length $ T.takeWhile isDigit t, t)
138+ n <- P decimal :: Parser Integer
140+ power <- perhaps 0 (char (`elem` "eE") >> signa (P decimal) :: Parser Int)
141+ return $! if fraction == 0
143+ then fromIntegral real
144+ else fromIntegral real * (10 ^^ power)
146+ then fromIntegral real + fromIntegral fraction /
148+ else (fromIntegral real + fromIntegral fraction /
149+ (10 ^ fracDigits)) * (10 ^^ power)