diff --git a/src/json.hpp b/src/json.hpp
index 9c0df9d497..0509e45649 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -8800,64 +8800,149 @@ class basic_json
             return result;
         }
 
-        /*!
-        @brief parse floating point number
+        // non locale aware isdigit
+        // Microsoft in 1252 codepage and others may classify additional single-byte characters as digits using std::isdigit
+        constexpr bool nl_isdigit(const char c) const
+        {
+            return c >= '0' and c <= '9';
+        }
 
-        This function (and its overloads) serves to select the most approprate
-        standard floating point number parsing function based on the type
-        supplied via the first parameter.  Set this to @a
-        static_cast<number_float_t*>(nullptr).
+        /*!
+        @brief parse string to floating point number
 
-        @param[in] type  the @ref number_float_t in use
+        This function is a partial reimplementation of the strtold in order to meet needs of JSON number
 
-        @param[in,out] endptr recieves a pointer to the first character after
-        the number
+        @param[in] str  the string we will parse
 
         @return the floating point number
         */
-        long double str_to_float_t(long double* /* type */, char** endptr) const
+        long double strtojnum(const char *str) const
         {
-            return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
-        }
+            long double result = 0;
+            char cp = *str;
+            int exp = 0; // exponent
+            {
+                const bool negative_sign = cp == '-';
 
-        /*!
-        @brief parse floating point number
+                if (cp == '-' or cp == '+')
+                {
+                    ++str;
+                }
 
-        This function (and its overloads) serves to select the most approprate
-        standard floating point number parsing function based on the type
-        supplied via the first parameter.  Set this to @a
-        static_cast<number_float_t*>(nullptr).
+                // read in fractional part of number, until an 'e' is reached.
+                // count digits after decimal point.
+                while (nl_isdigit(cp = *str))
+                {
+                     result = result * 10 + (cp - '0');
+                     ++str;
+                }
 
-        @param[in] type  the @ref number_float_t in use
+                if (cp == '.')
+                {
+                     while (nl_isdigit(cp = *++str))
+                     {
+                         result = result * 10 + (cp - '0');
+                         --exp;
+                     }
+                }
 
-        @param[in,out] endptr  recieves a pointer to the first character after
-        the number
+                // if negative number, reverse sign
+                if (negative_sign)
+                {
+                    result *= -1;
+                }
+            }
 
-        @return the floating point number
-        */
-        double str_to_float_t(double* /* type */, char** endptr) const
-        {
-            return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
-        }
+            // read in explicit exponent and calculate real exponent.
+            if (*str == 'e' or *str == 'E')
+            {
+                cp = *++str;
 
-        /*!
-        @brief parse floating point number
+                const bool negative_exp = cp == '-'; // read in exponent sign (+/-)
+                const bool plus_or_minus = (cp == '-' or cp == '+');
+                if (plus_or_minus)
+                {
+                     cp = *++str;
+                }
 
-        This function (and its overloads) serves to select the most approprate
-        standard floating point number parsing function based on the type
-        supplied via the first parameter.  Set this to @a
-        static_cast<number_float_t*>(nullptr).
+                int count = 0; // exponent calculation
+                if (not nl_isdigit(cp))
+                {
+                     if (plus_or_minus)
+                     {
+                         *--str;
+                     }
 
-        @param[in] type  the @ref number_float_t in use
+                     *--str;
+                     goto skip_loop;
+                }
 
-        @param[in,out] endptr  recieves a pointer to the first character after
-        the number
+                while (nl_isdigit(cp))
+                {
+                    constexpr int imax = std::numeric_limits<int>::max();
 
-        @return the floating point number
-        */
-        float str_to_float_t(float* /* type */, char** endptr) const
-        {
-            return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
+                    if ((imax - std::abs(exp) - (cp - '0')) / 10 > count)
+                    {
+                         count *= 10;
+                         count += cp - '0';
+                    }
+                    else
+                    {
+                        count = imax - exp;
+                        break;
+                    }
+
+                    cp = *++str;
+                }
+skip_loop:
+                exp += negative_exp ? -count : count;
+            }
+
+            // adjust number by powers of ten specified by format and exponent.
+            constexpr std::array<long double, 9> powerof10 = {
+                {1.e1L, 1.e2L, 1.e4L, 1.e8L, 1.e16L, 1.e32L, 1.e64L, 1.e128L, 1.e256L}
+            };
+
+            // round to INF if our exponent is larger than representable number
+            if (exp > std::numeric_limits<long double>::max_exponent10)
+            {
+                constexpr long double inf = std::numeric_limits<long double>::infinity();
+                result = (result < 0) ? -inf : inf;
+            }
+            // round to zero if our exponent is smaller than representable number
+            else if (exp < std::numeric_limits<long double>::min_exponent10)
+            {
+                result = 0.0L;
+            }
+            // iteratively divide result for negative exp
+            else if (exp < 0)
+            {
+                // make exp positive for loop below
+                exp *= -1;
+
+                // check enabled exp bits on lookup powerof10 lookup table
+                for (std::size_t count = 0; exp; ++count, exp >>= 1)
+                {
+                    if (exp & 1)
+                    {
+                        result /= powerof10[count];
+                    }
+                }
+            }
+            // iteratively multiply result for positive exp
+            else
+            {
+                // check enabled exp bits on lookup powerof10 lookup table
+                for (std::size_t count = 0; exp; ++count, exp >>= 1)
+                {
+                    if (exp & 1)
+                    {
+                        result *= powerof10[count];
+                    }
+                }
+            }
+
+            return result;
         }
 
         /*!
@@ -8958,8 +9043,8 @@ class basic_json
             }
             else
             {
-                // parse with strtod
-                result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
+                // convert string by json number format to floating point
+                result.m_value.number_float = strtojnum(reinterpret_cast<typename string_t::const_pointer>(m_start));
             }
 
             // save the type
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index 656e13b319..99631bbae2 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -8097,64 +8097,149 @@ class basic_json
             return result;
         }
 
-        /*!
-        @brief parse floating point number
+        // non locale aware isdigit
+        // Microsoft in 1252 codepage and others may classify additional single-byte characters as digits using std::isdigit
+        constexpr bool nl_isdigit(const char c) const
+        {
+            return c >= '0' and c <= '9';
+        }
 
-        This function (and its overloads) serves to select the most approprate
-        standard floating point number parsing function based on the type
-        supplied via the first parameter.  Set this to @a
-        static_cast<number_float_t*>(nullptr).
+        /*!
+        @brief parse string to floating point number
 
-        @param[in] type  the @ref number_float_t in use
+        This function is a partial reimplementation of the strtold in order to meet needs of JSON number
 
-        @param[in,out] endptr recieves a pointer to the first character after
-        the number
+        @param[in] str  the string we will parse
 
         @return the floating point number
         */
-        long double str_to_float_t(long double* /* type */, char** endptr) const
+        long double strtojnum(const char *str) const
         {
-            return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
-        }
+            long double result = 0;
+            char cp = *str;
+            int exp = 0; // exponent
+            {
+                const bool negative_sign = cp == '-';
 
-        /*!
-        @brief parse floating point number
+                if (cp == '-' or cp == '+')
+                {
+                    ++str;
+                }
 
-        This function (and its overloads) serves to select the most approprate
-        standard floating point number parsing function based on the type
-        supplied via the first parameter.  Set this to @a
-        static_cast<number_float_t*>(nullptr).
+                // read in fractional part of number, until an 'e' is reached.
+                // count digits after decimal point.
+                while (nl_isdigit(cp = *str))
+                {
+                     result = result * 10 + (cp - '0');
+                     ++str;
+                }
 
-        @param[in] type  the @ref number_float_t in use
+                if (cp == '.')
+                {
+                     while (nl_isdigit(cp = *++str))
+                     {
+                         result = result * 10 + (cp - '0');
+                         --exp;
+                     }
+                }
 
-        @param[in,out] endptr  recieves a pointer to the first character after
-        the number
+                // if negative number, reverse sign
+                if (negative_sign)
+                {
+                    result *= -1;
+                }
+            }
 
-        @return the floating point number
-        */
-        double str_to_float_t(double* /* type */, char** endptr) const
-        {
-            return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
-        }
+            // read in explicit exponent and calculate real exponent.
+            if (*str == 'e' or *str == 'E')
+            {
+                cp = *++str;
 
-        /*!
-        @brief parse floating point number
+                const bool negative_exp = cp == '-'; // read in exponent sign (+/-)
+                const bool plus_or_minus = (cp == '-' or cp == '+');
+                if (plus_or_minus)
+                {
+                     cp = *++str;
+                }
 
-        This function (and its overloads) serves to select the most approprate
-        standard floating point number parsing function based on the type
-        supplied via the first parameter.  Set this to @a
-        static_cast<number_float_t*>(nullptr).
+                int count = 0; // exponent calculation
+                if (not nl_isdigit(cp))
+                {
+                     if (plus_or_minus)
+                     {
+                         *--str;
+                     }
 
-        @param[in] type  the @ref number_float_t in use
+                     *--str;
+                     goto skip_loop;
+                }
 
-        @param[in,out] endptr  recieves a pointer to the first character after
-        the number
+                while (nl_isdigit(cp))
+                {
+                    constexpr int imax = std::numeric_limits<int>::max();
 
-        @return the floating point number
-        */
-        float str_to_float_t(float* /* type */, char** endptr) const
-        {
-            return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
+                    if ((imax - std::abs(exp) - (cp - '0')) / 10 > count)
+                    {
+                         count *= 10;
+                         count += cp - '0';
+                    }
+                    else
+                    {
+                        count = imax - exp;
+                        break;
+                    }
+
+                    cp = *++str;
+                }
+skip_loop:
+                exp += negative_exp ? -count : count;
+            }
+
+            // adjust number by powers of ten specified by format and exponent.
+            constexpr std::array<long double, 9> powerof10 = {
+                {1.e1L, 1.e2L, 1.e4L, 1.e8L, 1.e16L, 1.e32L, 1.e64L, 1.e128L, 1.e256L}
+            };
+
+            // round to INF if our exponent is larger than representable number
+            if (exp > std::numeric_limits<long double>::max_exponent10)
+            {
+                constexpr long double inf = std::numeric_limits<long double>::infinity();
+                result = (result < 0) ? -inf : inf;
+            }
+            // round to zero if our exponent is smaller than representable number
+            else if (exp < std::numeric_limits<long double>::min_exponent10)
+            {
+                result = 0.0L;
+            }
+            // iteratively divide result for negative exp
+            else if (exp < 0)
+            {
+                // make exp positive for loop below
+                exp *= -1;
+
+                // check enabled exp bits on lookup powerof10 lookup table
+                for (std::size_t count = 0; exp; ++count, exp >>= 1)
+                {
+                    if (exp & 1)
+                    {
+                        result /= powerof10[count];
+                    }
+                }
+            }
+            // iteratively multiply result for positive exp
+            else
+            {
+                // check enabled exp bits on lookup powerof10 lookup table
+                for (std::size_t count = 0; exp; ++count, exp >>= 1)
+                {
+                    if (exp & 1)
+                    {
+                        result *= powerof10[count];
+                    }
+                }
+            }
+
+            return result;
         }
 
         /*!
@@ -8255,8 +8340,8 @@ class basic_json
             }
             else
             {
-                // parse with strtod
-                result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL);
+                // convert string by json number format to floating point
+                result.m_value.number_float = strtojnum(reinterpret_cast<typename string_t::const_pointer>(m_start));
             }
 
             // save the type