diff --git a/Data/Attoparsec/ByteString/Char8.hs b/Data/Attoparsec/ByteString/Char8.hs
--- a/Data/Attoparsec/ByteString/Char8.hs
+++ b/Data/Attoparsec/ByteString/Char8.hs
@@ -105,6 +105,7 @@
     ) where
 
 import Control.Applicative (pure, (*>), (<*), (<$>), (<|>))
+import Control.Monad (void, when)
 import Data.Attoparsec.ByteString.FastSet (charClass, memberChar)
 import Data.Attoparsec.ByteString.Internal (Parser)
 import Data.Attoparsec.Combinator
@@ -113,8 +114,8 @@
 import Data.ByteString.Internal (c2w, w2c)
 import Data.Int (Int8, Int16, Int32, Int64)
 import Data.String (IsString(..))
-import Data.Scientific (Scientific, coefficient, base10Exponent)
-import qualified Data.Scientific as Sci (scientific)
+import Data.Scientific (Scientific)
+import qualified Data.Scientific as Sci
 import Data.Word (Word8, Word16, Word32, Word64, Word)
 import Prelude hiding (takeWhile)
 import qualified Data.Attoparsec.ByteString as A
@@ -495,7 +496,7 @@
 -- This function does not accept string representations of \"NaN\" or
 -- \"Infinity\".
 double :: Parser Double
-double = rational
+double = scientifically Sci.toRealFloat
 
 -- | Parse a number, attempting to preserve both speed and precision.
 --
@@ -510,11 +511,11 @@
 -- \"
 number :: Parser Number
 number = scientifically $ \s ->
-            let e = base10Exponent s
-                c = coefficient s
+            let e = Sci.base10Exponent s
+                c = Sci.coefficient s
             in if e >= 0
                then I (c * 10 ^ e)
-               else D (fromInteger c / 10 ^ negate e)
+               else D (Sci.toRealFloat s)
 
 -- | Parse a scientific number.
 --
@@ -522,29 +523,36 @@
 scientific :: Parser Scientific
 scientific = scientifically id
 
+-- A strict pair
+data SP = SP !Integer {-# UNPACK #-}!Int
+
 {-# INLINE scientifically #-}
 scientifically :: (Scientific -> a) -> Parser a
 scientifically h = do
   let minus = 45
       plus  = 43
-  !positive <- ((== plus) <$> I.satisfy (\c -> c == minus || c == plus)) <|>
-               pure True
+  sign <- I.peekWord8'
+  let !positive = sign == plus || sign /= minus
+  when (sign == plus || sign == minus) $
+    void $ I.anyWord8
 
   n <- decimal
 
-  let f fracDigits = Sci.scientific (B8.foldl' step n fracDigits)
-                                    (negate $ B8.length fracDigits)
+  let f fracDigits = SP (B8.foldl' step n fracDigits)
+                        (negate $ B8.length fracDigits)
       step a w = a * 10 + fromIntegral (w - 48)
 
-  s <- let dot = 46 in
-       (I.satisfy (==dot) *> (f <$> I.takeWhile isDigit_w8)) <|>
-         pure (Sci.scientific n 0)
+  dotty <- I.peekWord8
+  -- '.' -> ascii 46
+  SP c e <- case dotty of
+              Just 46 -> I.anyWord8 *> (f <$> I.takeWhile isDigit_w8)
+              _       -> pure (SP n 0)
 
-  let !signedCoeff | positive  =          coefficient s
-                   | otherwise = negate $ coefficient s
+  let !signedCoeff | positive  =  c
+                   | otherwise = -c
 
   let littleE = 101
       bigE    = 69
-  (I.satisfy (\c -> c == littleE || c == bigE) *>
-      fmap (h . Sci.scientific signedCoeff . (base10Exponent s +)) (signed decimal)) <|>
-    return (h $ Sci.scientific signedCoeff   (base10Exponent s))
+  (I.satisfy (\ex -> ex == littleE || ex == bigE) *>
+      fmap (h . Sci.scientific signedCoeff . (e +)) (signed decimal)) <|>
+    return (h $ Sci.scientific signedCoeff    e)
diff --git a/Data/Attoparsec/Text.hs b/Data/Attoparsec/Text.hs
--- a/Data/Attoparsec/Text.hs
+++ b/Data/Attoparsec/Text.hs
@@ -104,8 +104,8 @@
 import Control.Applicative (pure, (<$>), (*>), (<*), (<|>))
 import Data.Attoparsec.Combinator
 import Data.Attoparsec.Number (Number(..))
-import Data.Scientific (Scientific, coefficient, base10Exponent)
-import qualified Data.Scientific as Sci (scientific)
+import Data.Scientific (Scientific)
+import qualified Data.Scientific as Sci
 import Data.Attoparsec.Text.Internal (Parser, Result, parse, takeWhile1)
 import Data.Bits (Bits, (.|.), shiftL)
 import Data.Char (isAlpha, isDigit, isSpace, ord)
@@ -361,7 +361,7 @@
 -- This function does not accept string representations of \"NaN\" or
 -- \"Infinity\".
 double :: Parser Double
-double = rational
+double = scientifically Sci.toRealFloat
 
 -- | Parse a number, attempting to preserve both speed and precision.
 --
@@ -376,11 +376,11 @@
 -- \"Infinity\".
 number :: Parser Number
 number = scientifically $ \s ->
-            let e = base10Exponent s
-                c = coefficient s
+            let e = Sci.base10Exponent s
+                c = Sci.coefficient s
             in if e >= 0
                then I (c * 10 ^ e)
-               else D (fromInteger c / 10 ^ negate e)
+               else D (Sci.toRealFloat s)
 
 -- | Parse a scientific number.
 --
@@ -388,6 +388,9 @@
 scientific :: Parser Scientific
 scientific = scientifically id
 
+-- A strict pair
+data SP = SP !Integer {-# UNPACK #-}!Int
+
 {-# INLINE scientifically #-}
 scientifically :: (Scientific -> a) -> Parser a
 scientifically h = do
@@ -396,19 +399,19 @@
 
   n <- decimal
 
-  let f fracDigits = Sci.scientific (T.foldl' step n fracDigits)
-                                    (negate $ T.length fracDigits)
+  let f fracDigits = SP (T.foldl' step n fracDigits)
+                        (negate $ T.length fracDigits)
       step a c = a * 10 + fromIntegral (ord c - 48)
 
-  s <- (I.satisfy (=='.') *> (f <$> I.takeWhile isDigit)) <|>
-         pure (Sci.scientific n 0)
+  SP c e <- (I.satisfy (=='.') *> (f <$> I.takeWhile isDigit)) <|>
+            pure (SP n 0)
 
-  let !signedCoeff | positive  =          coefficient s
-                   | otherwise = negate $ coefficient s
+  let !signedCoeff | positive  =  c
+                   | otherwise = -c
 
-  (I.satisfy (\c -> c == 'e' || c == 'E') *>
-      fmap (h . Sci.scientific signedCoeff . (base10Exponent s +)) (signed decimal)) <|>
-    return (h $ Sci.scientific signedCoeff   (base10Exponent s))
+  (I.satisfy (\w -> w == 'e' || w == 'E') *>
+      fmap (h . Sci.scientific signedCoeff . (e +)) (signed decimal)) <|>
+    return (h $ Sci.scientific signedCoeff    e)
 
 -- | Parse a single digit, as recognised by 'isDigit'.
 digit :: Parser Char
diff --git a/attoparsec.cabal b/attoparsec.cabal
--- a/attoparsec.cabal
+++ b/attoparsec.cabal
@@ -1,5 +1,5 @@
 name:            attoparsec
-version:         0.11.3.2
+version:         0.11.3.3
 license:         BSD3
 license-file:    LICENSE
 category:        Text, Parsing
