diff --git a/src/string_utils.cpp b/src/string_utils.cpp
index 93a2588d058840628aec2789df78db11cf1fb6cd..ed73294c28931b8b568b69e65beae5090288d3b7 100644
--- a/src/string_utils.cpp
+++ b/src/string_utils.cpp
@@ -70,6 +70,16 @@ bstrToStdString(BSTR bstr)
 }
 #endif
 
+std::string
+to_string(double value)
+{
+    char buf[64];
+    int len = snprintf(buf, sizeof(buf), "%-.*G", 16, value);
+    if (len <= 0)
+        throw std::invalid_argument{"can't parse double"};
+    return {buf, (size_t)len};
+}
+
 std::string
 trim(const std::string &s)
 {
diff --git a/src/string_utils.h b/src/string_utils.h
index 63e6e3de67096f514e93e6d703da9ccd546148f2..8f27e78690b7cb490a838dc36a6d38aa5f8d476b 100644
--- a/src/string_utils.h
+++ b/src/string_utils.h
@@ -39,6 +39,8 @@ bool_to_str(bool b) noexcept
     return b ? TRUE_STR : FALSE_STR;
 }
 
+std::string to_string(double value);
+
 #ifdef _WIN32
 std::wstring to_wstring(const std::string& s);
 std::string decodeMultibyteString(const std::string& s);
diff --git a/test/unitTest/string_utils/testString_utils.cpp b/test/unitTest/string_utils/testString_utils.cpp
index b85e90c2a6c2e616155f088c6290dc5962d3c6ad..3ebb76c3e8581102dbb29169cb6f2e2a5af90b6a 100644
--- a/test/unitTest/string_utils/testString_utils.cpp
+++ b/test/unitTest/string_utils/testString_utils.cpp
@@ -45,9 +45,9 @@ private:
     CPPUNIT_TEST(split_string_test);
     CPPUNIT_TEST_SUITE_END();
 
-    const double DOUBLE = 3.141593;
+    const double DOUBLE = 3.14159265359;
     const int INT = 42 ;
-    const std::string PI_DOUBLE = "3.141593";
+    const std::string PI_DOUBLE = "3.14159265359";
     const std::string PI_FLOAT = "3.14159265359";
     const std::string PI_42 = "42";
 };
@@ -65,11 +65,11 @@ void
 StringUtilsTest::to_string_test()
 {
     // test with double
-    CPPUNIT_ASSERT(std::to_string(DOUBLE) == PI_DOUBLE);
+    CPPUNIT_ASSERT(to_string(DOUBLE) == PI_DOUBLE);
 
     // test with float
     float varFloat = 3.14;
-    std::string sVarFloat = std::to_string(varFloat);
+    std::string sVarFloat = to_string(varFloat);
     CPPUNIT_ASSERT(sVarFloat.at(0) == '3' && sVarFloat.at(1) == '.'
                    && sVarFloat.at(2) == '1' && sVarFloat.at(3) == '4');