ICU-20974 Correctly handle extreme values of double.
diff --git a/icu4c/source/i18n/number_decimalquantity.cpp b/icu4c/source/i18n/number_decimalquantity.cpp
index 2c584a4..482e93d 100644
--- a/icu4c/source/i18n/number_decimalquantity.cpp
+++ b/icu4c/source/i18n/number_decimalquantity.cpp
@@ -439,9 +439,6 @@ void DecimalQuantity::_setToDoubleFast(double n) {
     // TODO: Make a fast path for other types of doubles.
     if (!std::numeric_limits<double>::is_iec559) {
         convertToAccurateDouble();
-        // Turn off the approximate double flag, since the value is now exact.
-        isApproximate = false;
-        origDouble = 0.0;
         return;
     }
 
@@ -456,8 +453,14 @@ void DecimalQuantity::_setToDoubleFast(double n) {
         return;
     }
 
+    if (exponent == -1023 || exponent == 1024) {
+        // The extreme values of exponent are special; use slow path.
+        convertToAccurateDouble();
+        return;
+    }
+
     // 3.3219... is log2(10)
-    auto fracLength = static_cast<int32_t> ((52 - exponent) / 3.32192809489);
+    auto fracLength = static_cast<int32_t> ((52 - exponent) / 3.32192809488736234787031942948939017586);
     if (fracLength >= 0) {
         int32_t i = fracLength;
         // 1e22 is the largest exact double.
diff --git a/icu4c/source/test/intltest/numbertest_api.cpp b/icu4c/source/test/intltest/numbertest_api.cpp
index 98c8ceb..01494ff 100644
--- a/icu4c/source/test/intltest/numbertest_api.cpp
+++ b/icu4c/source/test/intltest/numbertest_api.cpp
@@ -1391,6 +1391,30 @@ void NumberFormatterApiTest::roundingOther() {
             u"1",
             u"1",
             u"0");
+
+    assertFormatSingle(
+            u"ICU-20974 Double.MIN_NORMAL",
+            u"scientific",
+            u"E0",
+            NumberFormatter::with().notation(Notation::scientific()),
+            Locale::getEnglish(),
+            DBL_MIN,
+            u"2.225074E-308");
+
+#ifndef DBL_TRUE_MIN
+#define DBL_TRUE_MIN 4.9E-324
+#endif
+
+    // Note: this behavior is intentionally different from Java; see
+    // https://github.com/google/double-conversion/issues/126
+    assertFormatSingle(
+            u"ICU-20974 Double.MIN_VALUE",
+            u"scientific",
+            u"E0",
+            NumberFormatter::with().notation(Notation::scientific()),
+            Locale::getEnglish(),
+            DBL_TRUE_MIN,
+            u"5E-324");
 }
 
 void NumberFormatterApiTest::grouping() {
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java
index 5873bab..b1ead76 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java
@@ -488,8 +488,14 @@ private void _setToDoubleFast(double n) {
             return;
         }
 
+        if (exponent == -1023 || exponent == 1024) {
+            // The extreme values of exponent are special; use slow path.
+            convertToAccurateDouble();
+            return;
+        }
+
         // 3.3219... is log2(10)
-        int fracLength = (int) ((52 - exponent) / 3.32192809489);
+        int fracLength = (int) ((52 - exponent) / 3.32192809488736234787031942948939017586);
         if (fracLength >= 0) {
             int i = fracLength;
             // 1e22 is the largest exact double.
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java
index 4188068..2512b1f 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java
@@ -1350,6 +1350,24 @@ public void roundingOther() {
                 "1",
                 "1",
                 "0");
+
+        assertFormatSingle(
+                "ICU-20974 Double.MIN_NORMAL",
+                "scientific",
+                "E0",
+                NumberFormatter.with().notation(Notation.scientific()),
+                ULocale.ENGLISH,
+                Double.MIN_NORMAL,
+                "2.225074E-308");
+
+        assertFormatSingle(
+                "ICU-20974 Double.MIN_VALUE",
+                "scientific",
+                "E0",
+                NumberFormatter.with().notation(Notation.scientific()),
+                ULocale.ENGLISH,
+                Double.MIN_VALUE,
+                "4.9E-324");
     }
 
     @Test