diff --git a/src/ArduinoJson/Numbers/FloatParts.hpp b/src/ArduinoJson/Numbers/FloatParts.hpp
index 67344494..b9291ce1 100644
--- a/src/ArduinoJson/Numbers/FloatParts.hpp
+++ b/src/ArduinoJson/Numbers/FloatParts.hpp
@@ -63,8 +63,8 @@ struct FloatParts {
 
     if (value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD) {
       for (; index >= 0; index--) {
-        if (value >= traits::positiveBinaryPowerOfTen(index)) {
-          value *= traits::negativeBinaryPowerOfTen(index);
+        if (value >= traits::positiveBinaryPowersOfTen()[index]) {
+          value *= traits::negativeBinaryPowersOfTen()[index];
           powersOf10 = int16_t(powersOf10 + bit);
         }
         bit >>= 1;
@@ -73,8 +73,8 @@ struct FloatParts {
 
     if (value > 0 && value <= ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD) {
       for (; index >= 0; index--) {
-        if (value < traits::negativeBinaryPowerOfTenPlusOne(index)) {
-          value *= traits::positiveBinaryPowerOfTen(index);
+        if (value < traits::negativeBinaryPowersOfTenPlusOne()[index]) {
+          value *= traits::positiveBinaryPowersOfTen()[index];
           powersOf10 = int16_t(powersOf10 - bit);
         }
         bit >>= 1;
diff --git a/src/ArduinoJson/Numbers/FloatTraits.hpp b/src/ArduinoJson/Numbers/FloatTraits.hpp
index 030fd54d..5736f599 100644
--- a/src/ArduinoJson/Numbers/FloatTraits.hpp
+++ b/src/ArduinoJson/Numbers/FloatTraits.hpp
@@ -34,21 +34,21 @@ struct FloatTraits {
     if (e > 0) {
       for (uint8_t index = 0; e != 0; index++) {
         if (e & 1)
-          m *= positiveBinaryPowerOfTen(index);
+          m *= positiveBinaryPowersOfTen()[index];
         e >>= 1;
       }
     } else {
       e = TExponent(-e);
       for (uint8_t index = 0; e != 0; index++) {
         if (e & 1)
-          m *= negativeBinaryPowerOfTen(index);
+          m *= negativeBinaryPowersOfTen()[index];
         e >>= 1;
       }
     }
     return m;
   }
 
-  static T positiveBinaryPowerOfTen(int index) {
+  static pgm_ptr positiveBinaryPowersOfTen() {
     ARDUINOJSON_DEFINE_PROGMEM_ARRAY(  //
         uint64_t, factors,
         {
@@ -62,10 +62,10 @@ struct FloatTraits {
             0x5A827748F9301D32,  // 1e128
             0x75154FDD7F73BF3C,  // 1e256
         });
-    return forge(pgm_read(factors + index));
+    return pgm_ptr(reinterpret_cast(factors));
   }
 
-  static T negativeBinaryPowerOfTen(int index) {
+  static pgm_ptr negativeBinaryPowersOfTen() {
     ARDUINOJSON_DEFINE_PROGMEM_ARRAY(  //
         uint64_t, factors,
         {
@@ -79,10 +79,10 @@ struct FloatTraits {
             0x255BBA08CF8C979D,  // 1e-128
             0x0AC8062864AC6F43   // 1e-256
         });
-    return forge(pgm_read(factors + index));
+    return pgm_ptr(reinterpret_cast(factors));
   }
 
-  static T negativeBinaryPowerOfTenPlusOne(int index) {
+  static pgm_ptr negativeBinaryPowersOfTenPlusOne() {
     ARDUINOJSON_DEFINE_PROGMEM_ARRAY(  //
         uint64_t, factors,
         {
@@ -96,7 +96,7 @@ struct FloatTraits {
             0x2591544581B7DEC2,  // 1e-127
             0x0AFE07B27DD78B14   // 1e-255
         });
-    return forge(pgm_read(factors + index));
+    return pgm_ptr(reinterpret_cast(factors));
   }
 
   static T nan() {
@@ -154,21 +154,21 @@ struct FloatTraits {
     if (e > 0) {
       for (uint8_t index = 0; e != 0; index++) {
         if (e & 1)
-          m *= positiveBinaryPowerOfTen(index);
+          m *= positiveBinaryPowersOfTen()[index];
         e >>= 1;
       }
     } else {
       e = -e;
       for (uint8_t index = 0; e != 0; index++) {
         if (e & 1)
-          m *= negativeBinaryPowerOfTen(index);
+          m *= negativeBinaryPowersOfTen()[index];
         e >>= 1;
       }
     }
     return m;
   }
 
-  static T positiveBinaryPowerOfTen(int index) {
+  static pgm_ptr positiveBinaryPowersOfTen() {
     ARDUINOJSON_DEFINE_PROGMEM_ARRAY(uint32_t, factors,
                                      {
                                          0x41200000,  // 1e1f
@@ -178,10 +178,10 @@ struct FloatTraits {
                                          0x5a0e1bca,  // 1e16f
                                          0x749dc5ae   // 1e32f
                                      });
-    return forge(pgm_read(factors + index));
+    return pgm_ptr(reinterpret_cast(factors));
   }
 
-  static T negativeBinaryPowerOfTen(int index) {
+  static pgm_ptr negativeBinaryPowersOfTen() {
     ARDUINOJSON_DEFINE_PROGMEM_ARRAY(uint32_t, factors,
                                      {
                                          0x3dcccccd,  // 1e-1f
@@ -191,10 +191,10 @@ struct FloatTraits {
                                          0x24e69595,  // 1e-16f
                                          0x0a4fb11f   // 1e-32f
                                      });
-    return forge(pgm_read(factors + index));
+    return pgm_ptr(reinterpret_cast(factors));
   }
 
-  static T negativeBinaryPowerOfTenPlusOne(int index) {
+  static pgm_ptr negativeBinaryPowersOfTenPlusOne() {
     ARDUINOJSON_DEFINE_PROGMEM_ARRAY(uint32_t, factors,
                                      {
                                          0x3f800000,  // 1e0f
@@ -204,7 +204,7 @@ struct FloatTraits {
                                          0x26901d7d,  // 1e-15f
                                          0x0c01ceb3   // 1e-31f
                                      });
-    return forge(pgm_read(factors + index));
+    return pgm_ptr(reinterpret_cast(factors));
   }
 
   static T forge(uint32_t bits) {
diff --git a/src/ArduinoJson/Polyfills/pgmspace.hpp b/src/ArduinoJson/Polyfills/pgmspace.hpp
index 5cfd28cb..03adc6f1 100644
--- a/src/ArduinoJson/Polyfills/pgmspace.hpp
+++ b/src/ArduinoJson/Polyfills/pgmspace.hpp
@@ -106,6 +106,29 @@ inline uint32_t pgm_read_dword(ArduinoJson::detail::pgm_p p) {
 }
 #endif
 
+#ifndef pgm_read_float
+inline float pgm_read_float(ArduinoJson::detail::pgm_p p) {
+  float result;
+  memcpy_P(&result, p.address, sizeof(float));
+  return result;
+}
+#endif
+
+#ifndef pgm_read_double
+#  if defined(__SIZEOF_DOUBLE__) && defined(__SIZEOF_FLOAT__) && \
+      __SIZEOF_DOUBLE__ == __SIZEOF_FLOAT__
+inline double pgm_read_double(ArduinoJson::detail::pgm_p p) {
+  return pgm_read_float(p.address);
+}
+#  else
+inline double pgm_read_double(ArduinoJson::detail::pgm_p p) {
+  double result;
+  memcpy_P(&result, p.address, sizeof(double));
+  return result;
+}
+#  endif
+#endif
+
 #ifndef pgm_read_ptr
 inline void* pgm_read_ptr(ArduinoJson::detail::pgm_p p) {
   void* result;
diff --git a/src/ArduinoJson/Polyfills/pgmspace_generic.hpp b/src/ArduinoJson/Polyfills/pgmspace_generic.hpp
index f5b50b8d..750bb438 100644
--- a/src/ArduinoJson/Polyfills/pgmspace_generic.hpp
+++ b/src/ArduinoJson/Polyfills/pgmspace_generic.hpp
@@ -29,11 +29,12 @@ inline uint32_t pgm_read(const uint32_t* p) {
   return pgm_read_dword(p);
 }
 
-template 
-inline T pgm_read(const T* p) {
-  T result;
-  memcpy_P(&result, p, sizeof(T));
-  return result;
+inline double pgm_read(const double* p) {
+  return pgm_read_double(p);
+}
+
+inline float pgm_read(const float* p) {
+  return pgm_read_float(p);
 }
 
 #else
@@ -50,4 +51,17 @@ inline T pgm_read(const T* p) {
 
 #endif
 
+template 
+class pgm_ptr {
+ public:
+  explicit pgm_ptr(const T* ptr) : _ptr(ptr) {}
+
+  T operator[](intptr_t index) const {
+    return pgm_read(_ptr + index);
+  }
+
+ private:
+  const T* _ptr;
+};
+
 ARDUINOJSON_END_PRIVATE_NAMESPACE