diff --git a/cbits/dtoa.c b/cbits/dtoa.c
--- a/cbits/dtoa.c
+++ b/cbits/dtoa.c
@@ -343,18 +343,36 @@
   decimals = MIN(-d_exp, MAX(1, len-1));
   if (d_exp < 0 && len > 1) // Add decimal point?
   {
-    for(i = 0; i < decimals; ++i) dst[len-i] = dst[len-i-1];
-    dst[len++ - decimals] = '.';
+    int dot_pos = len-decimals;
+    if (dot_pos == 0) {
+      for(i = 0; i < decimals; ++i) {
+        dst[len-i+1] = dst[len-i-1];
+      }
+      // put a 0 in front of the decimal point to make it a valid Haskell floating point number.
+      dst[0] = '0';
+      dst[1] = '.';
+      len+= 2;
+    } else {
+      for(i = 0; i < decimals; ++i) {
+        dst[len-i] = dst[len-i-1];
+      }
+      dst[dot_pos] = '.';
+      len++;
+    }
+
     d_exp += decimals;
     // Need scientific notation as well?
     if (d_exp != 0) { dst[len++] = 'e'; len += i_to_str(d_exp, dst+len); }
   }
   else if (d_exp < 0 && d_exp >= -3) // Add decimal point for numbers of form 0.000x where it's shorter?
   {
-    for(i = 0; i < len; ++i) dst[len-d_exp-1-i] = dst[len-i-1];
-    dst[0] = '.';
-    for(i = 1; i < -d_exp; ++i) dst[i] = '0';
-    len += -d_exp;
+    // len here is 1!
+    dst[1-d_exp] = dst[0];
+    // put a 0 in front of the decimal point to make it a valid Haskell floating point number.
+    dst[0] = '0';
+    dst[1] = '.';
+    for(i = 2; i < (1-d_exp); ++i) dst[i] = '0';
+    len += -d_exp+1;
   }
   // Add scientific notation?
   else if (d_exp < 0 || d_exp > 2) { dst[len++] = 'e'; len += i_to_str(d_exp, dst+len); }
diff --git a/library/PtrPoker/ByteString.hs b/library/PtrPoker/ByteString.hs
--- a/library/PtrPoker/ByteString.hs
+++ b/library/PtrPoker/ByteString.hs
@@ -29,7 +29,7 @@
 
 double :: Double -> ByteString
 double dbl =
-  unsafeCreateUptoN 24 (\ ptr ->
+  unsafeCreateUptoN 25 (\ ptr ->
     Ffi.pokeDouble dbl ptr
       & fmap fromIntegral)
 
diff --git a/library/PtrPoker/Write.hs b/library/PtrPoker/Write.hs
--- a/library/PtrPoker/Write.hs
+++ b/library/PtrPoker/Write.hs
@@ -1,7 +1,7 @@
 module PtrPoker.Write
 where
 
-import PtrPoker.Prelude
+import PtrPoker.Prelude hiding (concat)
 import qualified PtrPoker.IO.ByteString as ByteStringIO
 import qualified PtrPoker.IO.Prim as PrimIO
 import qualified PtrPoker.Poke as Poke
@@ -35,11 +35,17 @@
   {-# INLINE (<>) #-}
   Write lSize lPoke <> Write rSize rPoke =
     Write (lSize + rSize) (lPoke <> rPoke)
+  {-# INLINE sconcat #-}
+  sconcat =
+    concat
 
 instance Monoid Write where
   {-# INLINE mempty #-}
   mempty =
     Write 0 mempty
+  {-# INLINE mconcat #-}
+  mconcat =
+    concat
 
 {-|
 Reuses the IsString instance of 'ByteString'.
@@ -48,6 +54,16 @@
   {-# INLINE fromString #-}
   fromString =
     byteString . fromString
+
+{-|
+Concatenate a foldable of writes.
+-}
+{-# INLINE concat #-}
+concat :: Foldable f => f Write -> Write
+concat f =
+  Write
+    (foldl' (\ a b -> a + writeSize b) 0 f)
+    (Poke.Poke (\ p -> foldM (\ p write -> Poke.pokePtr (writePoke write) p) p f))
 
 {-|
 Render Word8 as byte.
diff --git a/ptr-poker.cabal b/ptr-poker.cabal
--- a/ptr-poker.cabal
+++ b/ptr-poker.cabal
@@ -1,5 +1,5 @@
 name: ptr-poker
-version: 0.1.1.2
+version: 0.1.1.3
 synopsis: Pointer poking action construction and composition toolkit
 homepage: https://github.com/nikita-volkov/ptr-poker
 bug-reports: https://github.com/nikita-volkov/ptr-poker/issues
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -110,4 +110,16 @@
   Gen.element [0 / 0, 1 / 0, (-1) / 0, -0]
 
 realRealFloatGen =
+  Gen.frequency [
+    (50, fullRangeExponentialRealFloatGen)
+    ,
+    (50, simpleZeroToOneRealFloatGen)
+    ]
+
+fullRangeExponentialRealFloatGen =
   Gen.realFloat (Range.exponentialFloat NumericLimits.minValue NumericLimits.maxValue)
+
+simpleZeroToOneRealFloatGen =
+  do
+    int <- Gen.int (Range.exponential 0 999999)
+    return (read ("0." <> show int))
