diff --git a/py/formatfloat.c b/py/formatfloat.c
index 64f0131471143872082c6ad71018af2b38eb630c..cc06361008574af888c8dc673d7d2bd85ace0bef 100644
--- a/py/formatfloat.c
+++ b/py/formatfloat.c
@@ -24,10 +24,15 @@
  * THE SOFTWARE.
  */
 
+#include <stdlib.h>
+#include <stdint.h>
+#include "py/formatfloat.h"
+
+#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
 /***********************************************************************
 
-  formatfloat.c  - Ruutine for converting a single-precision floating
-                    point number into a string.
+  Routine for converting a single-precision floating
+  point number into a string.
 
   The code in this funcion was inspired from Fred Bayer's pdouble.c.
   Since pdouble.c was released as Public Domain, I'm releasing this
@@ -39,15 +44,6 @@
 
 ***********************************************************************/
 
-#include <stdlib.h>
-#include <stdint.h>
-
-#include "py/mpconfig.h"
-
-#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
-
-#include "py/formatfloat.h"
-
 // 1 sign bit, 8 exponent bits, and 23 mantissa bits.
 // exponent values 0 and 255 are reserved, exponent can be 1 to 254.
 // exponent is stored with a bias of 127.
@@ -341,4 +337,76 @@ int mp_format_float(float f, char *buf, size_t buf_size, char fmt, int prec, cha
     return s - buf;
 }
 
+#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
+
+#include <errno.h>
+#include <stdio.h>
+
+#ifdef _MSC_VER
+// For msvc we need to address some quirks in the snprintf implementation:
+// - there is no standard snprintf, it is named _snprintf instead
+// - 'F' format isn't handled so use 'f'
+// - nan and inf are printed as 1.#QNAN and 1.#INF
+#include <math.h>
+#include <string.h>
+
+STATIC int copy_with_sign(char *dest, size_t bufSize, const char *value, char sign) {
+    if (bufSize == 0) {
+        return 0;
+    }
+    size_t numSignChars = 0;
+    if (sign) {
+        *dest = sign;
+        ++numSignChars;
+    }
+    // check total length including terminator
+    size_t length = strlen(value) + 1 + numSignChars;
+    if (length > bufSize) {
+        length = bufSize;
+    }
+    // length without terminator
+    --length;
+    if (length > numSignChars) {
+        memcpy(dest + numSignChars, value, length - numSignChars);
+    }
+    dest[length] = 0;
+    return length;
+}
+
+#define snprintf _snprintf
+#endif
+
+int mp_format_float(double value, char *buf, size_t bufSize, char fmt, int prec, char sign) {
+    if (!buf) {
+        errno = EINVAL;
+        return -1;
+    }
+#ifdef _MSC_VER
+    if (isnan(value)) {
+        return copy_with_sign(buf, bufSize, "nan", sign);
+    } else if (isinf(value)) {
+        return copy_with_sign(buf, bufSize, "inf", value > 0.0 ? sign : '-');
+    } else {
+        if (fmt == 'F') {
+            fmt = 'f';
+        }
+#endif
+        char fmt_buf[6];
+        char *fmt_s = fmt_buf;
+
+        *fmt_s++ = '%';
+        if (sign) {
+            *fmt_s++ = sign;
+        }
+        *fmt_s++ = '.';
+        *fmt_s++ = '*';
+        *fmt_s++ = fmt;
+        *fmt_s = '\0';
+
+        return snprintf(buf, bufSize, fmt_buf, prec, value);
+#ifdef _MSC_VER
+    }
+#endif
+}
+
 #endif
diff --git a/py/formatfloat.h b/py/formatfloat.h
index 1eb2c1e46f2751af08b401bf1f41ffb24520533e..019603447171e7302b55a6932c38c6caa49fdeed 100644
--- a/py/formatfloat.h
+++ b/py/formatfloat.h
@@ -26,6 +26,10 @@
 #ifndef __MICROPY_INCLUDED_PY_FORMATFLOAT_H__
 #define __MICROPY_INCLUDED_PY_FORMATFLOAT_H__
 
-int mp_format_float(float f, char *buf, size_t bufSize, char fmt, int prec, char sign);
+#include "py/mpconfig.h"
+
+#if MICROPY_PY_BUILTINS_FLOAT
+int mp_format_float(mp_float_t f, char *buf, size_t bufSize, char fmt, int prec, char sign);
+#endif
 
 #endif // __MICROPY_INCLUDED_PY_FORMATFLOAT_H__
diff --git a/py/mpprint.c b/py/mpprint.c
index 99d0357af849f4f550451dd47966969f2917b3e7..78a0b7aa557c234cbba5e638ee7940b3728bf7e0 100644
--- a/py/mpprint.c
+++ b/py/mpprint.c
@@ -35,10 +35,6 @@
 #include "py/objint.h"
 #include "py/runtime.h"
 
-#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
-#include <stdio.h>
-#endif
-
 #if MICROPY_PY_BUILTINS_FLOAT
 #include "py/formatfloat.h"
 #endif
@@ -340,29 +336,12 @@ int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, c
     if (flags & PF_FLAG_SPACE_SIGN) {
         sign = ' ';
     }
-    int len;
-#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
-    len = mp_format_float(f, buf, sizeof(buf), fmt, prec, sign);
-#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
-    char fmt_buf[6];
-    char *fmt_s = fmt_buf;
 
-    *fmt_s++ = '%';
-    if (sign) {
-        *fmt_s++ = sign;
-    }
-    *fmt_s++ = '.';
-    *fmt_s++ = '*';
-    *fmt_s++ = fmt;
-    *fmt_s = '\0';
-
-    len = snprintf(buf, sizeof(buf), fmt_buf, prec, f);
+    int len = mp_format_float(f, buf, sizeof(buf), fmt, prec, sign);
     if (len < 0) {
         len = 0;
     }
-#else
-#error Unknown MICROPY FLOAT IMPL
-#endif
+
     char *s = buf;
 
     if ((flags & PF_FLAG_ADD_PERCENT) && (size_t)(len + 1) < sizeof(buf)) {
diff --git a/py/objcomplex.c b/py/objcomplex.c
index 8a424f7f269bacadfa23a9d30ce3181a7448450c..b790b05638bf23a05bcbdf1533d4dfef88abc64b 100644
--- a/py/objcomplex.c
+++ b/py/objcomplex.c
@@ -37,10 +37,7 @@
 #if MICROPY_PY_BUILTINS_COMPLEX
 
 #include <math.h>
-
-#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
 #include "py/formatfloat.h"
-#endif
 
 typedef struct _mp_obj_complex_t {
     mp_obj_base_t base;
@@ -53,33 +50,23 @@ STATIC void complex_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_
     mp_obj_complex_t *o = o_in;
 #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
     char buf[16];
-    if (o->real == 0) {
-        mp_format_float(o->imag, buf, sizeof(buf), 'g', 7, '\0');
-        mp_printf(print, "%sj", buf);
-    } else {
-        mp_format_float(o->real, buf, sizeof(buf), 'g', 7, '\0');
-        mp_printf(print, "(%s", buf);
-        if (o->imag >= 0 || isnan(o->imag)) {
-            mp_print_str(print, "+");
-        }
-        mp_format_float(o->imag, buf, sizeof(buf), 'g', 7, '\0');
-        mp_printf(print, "%sj)", buf);
-    }
+    const int precision = 7;
 #else
     char buf[32];
+    const int precision = 16;
+#endif
     if (o->real == 0) {
-        sprintf(buf, "%.16g", (double)o->imag);
+        mp_format_float(o->imag, buf, sizeof(buf), 'g', precision, '\0');
         mp_printf(print, "%sj", buf);
     } else {
-        sprintf(buf, "%.16g", (double)o->real);
+        mp_format_float(o->real, buf, sizeof(buf), 'g', precision, '\0');
         mp_printf(print, "(%s", buf);
         if (o->imag >= 0 || isnan(o->imag)) {
             mp_print_str(print, "+");
         }
-        sprintf(buf, "%.16g", (double)o->imag);
+        mp_format_float(o->imag, buf, sizeof(buf), 'g', precision, '\0');
         mp_printf(print, "%sj)", buf);
     }
-#endif
 }
 
 STATIC mp_obj_t complex_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
diff --git a/py/objfloat.c b/py/objfloat.c
index f74e12f9d40dfdcd7698689dbd1167ab661a1de4..ffb3c7196486d3083f735b2cf85b1c964ffb2171 100644
--- a/py/objfloat.c
+++ b/py/objfloat.c
@@ -37,31 +37,24 @@
 #if MICROPY_PY_BUILTINS_FLOAT
 
 #include <math.h>
-
-#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
 #include "py/formatfloat.h"
-#endif
 
 STATIC void float_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
     (void)kind;
     mp_obj_float_t *o = o_in;
 #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
     char buf[16];
-    mp_format_float(o->value, buf, sizeof(buf), 'g', 7, '\0');
-    mp_print_str(print, buf);
-    if (strchr(buf, '.') == NULL && strchr(buf, 'e') == NULL && strchr(buf, 'n') == NULL) {
-        // Python floats always have decimal point (unless inf or nan)
-        mp_print_str(print, ".0");
-    }
+    const int precision = 7;
 #else
     char buf[32];
-    sprintf(buf, "%.16g", (double) o->value);
+    const int precision = 16;
+#endif
+    mp_format_float(o->value, buf, sizeof(buf), 'g', precision, '\0');
     mp_print_str(print, buf);
     if (strchr(buf, '.') == NULL && strchr(buf, 'e') == NULL && strchr(buf, 'n') == NULL) {
         // Python floats always have decimal point (unless inf or nan)
         mp_print_str(print, ".0");
     }
-#endif
 }
 
 STATIC mp_obj_t float_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
diff --git a/tests/float/float1.py b/tests/float/float1.py
index f670a63486f06b1f05f95060b0e98ff9831fd8ba..935375c4760c2e76ae71360520ddff5056e61254 100644
--- a/tests/float/float1.py
+++ b/tests/float/float1.py
@@ -13,6 +13,7 @@ print(float("1e1"))
 print(float("1e+1"))
 print(float("1e-1"))
 print(float("inf"))
+print(float("-inf"))
 print(float("INF"))
 print(float("infinity"))
 print(float("INFINITY"))
diff --git a/windows/mpconfigport.h b/windows/mpconfigport.h
index 8b1eaacf76d7038eac9f888a0ed4116256353178..70c06d3e5fcca244553b19b2bc5f852f57c5b60e 100644
--- a/windows/mpconfigport.h
+++ b/windows/mpconfigport.h
@@ -198,7 +198,4 @@ void msec_sleep(double msec);
 #include <stddef.h> //for NULL
 #include <assert.h> //for assert
 
-// Functions implemented in platform code
-
-int snprintf(char *dest, size_t count, const char *format, ...);
 #endif
diff --git a/windows/msvc/snprintf.c b/windows/msvc/snprintf.c
deleted file mode 100644
index d200a4cbc81a557408ba283be67e9f1acf2d3146..0000000000000000000000000000000000000000
--- a/windows/msvc/snprintf.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-* This file is part of the Micro Python project, http://micropython.org/
-*
-* The MIT License (MIT)
-*
-* Copyright (c) 2013, 2014 Damien P. George
-*
-* Permission is hereby granted, free of charge, to any person obtaining a copy
-* of this software and associated documentation files (the "Software"), to deal
-* in the Software without restriction, including without limitation the rights
-* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-* copies of the Software, and to permit persons to whom the Software is
-* furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included in
-* all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-* THE SOFTWARE.
-*/
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <malloc.h>
-
-// _snprintf/vsnprintf are fine, except the 'F' specifier is not handled
-int snprintf(char *dest, size_t count, const char *format, ...) {
-    const size_t fmtLen = strlen(format) + 1;
-    char *fixedFmt = alloca(fmtLen);
-    for (size_t i = 0; i < fmtLen; ++i)
-        fixedFmt[i] = format[i] == 'F' ? 'f' : format[i];
-
-    va_list args;
-    va_start(args, format);
-    const int ret = vsnprintf(dest, count, fixedFmt, args);
-    va_end(args);
-
-    return ret;
-}