diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index 6a717f19bb..84d37de930 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -1565,7 +1565,7 @@ dpow(PG_FUNCTION_ARGS)
 
 	if (unlikely(isinf(result)) && !isinf(arg1) && !isinf(arg2))
 		float_overflow_error();
-	if (unlikely(result == 0.0) && arg1 != 0.0)
+	if (unlikely(result == 0.0) && arg1 != 0.0 && !isinf(arg1) && !isinf(arg2))
 		float_underflow_error();
 
 	PG_RETURN_FLOAT8(result);
@@ -1581,15 +1581,38 @@ dexp(PG_FUNCTION_ARGS)
 	float8		arg1 = PG_GETARG_FLOAT8(0);
 	float8		result;
 
-	errno = 0;
-	result = exp(arg1);
-	if (errno == ERANGE && result != 0 && !isinf(result))
-		result = get_float8_infinity();
-
-	if (unlikely(isinf(result)) && !isinf(arg1))
-		float_overflow_error();
-	if (unlikely(result == 0.0))
-		float_underflow_error();
+	/*
+	 * Handle NaN and Inf cases explicitly.  This avoids needing to assume
+	 * that the platform's exp() conforms to POSIX for these cases, and it
+	 * removes some edge cases for the overflow checks below.
+	 */
+	if (isnan(arg1))
+		result = arg1;
+	else if (isinf(arg1))
+	{
+		/* Per POSIX, exp(-Inf) is 0 */
+		result = (arg1 > 0.0) ? arg1 : 0;
+	}
+	else
+	{
+		/*
+		 * On some platforms, exp() will not set errno but just return Inf or
+		 * zero to report overflow/underflow; therefore, test both cases.
+		 */
+		errno = 0;
+		result = exp(arg1);
+		if (unlikely(errno == ERANGE))
+		{
+			if (result != 0.0)
+				float_overflow_error();
+			else
+				float_underflow_error();
+		}
+		else if (unlikely(isinf(result)))
+			float_overflow_error();
+		else if (unlikely(result == 0.0))
+			float_underflow_error();
+	}
 
 	PG_RETURN_FLOAT8(result);
 }
diff --git a/src/test/regress/expected/float8.out b/src/test/regress/expected/float8.out
index aaef20bcfd..3957fb58d8 100644
--- a/src/test/regress/expected/float8.out
+++ b/src/test/regress/expected/float8.out
@@ -385,6 +385,158 @@ SELECT power(float8 'NaN', float8 '0');
      1
 (1 row)
 
+SELECT power(float8 'inf', float8 '0');
+ power 
+-------
+     1
+(1 row)
+
+SELECT power(float8 '-inf', float8 '0');
+ power 
+-------
+     1
+(1 row)
+
+SELECT power(float8 '0', float8 'inf');
+ power 
+-------
+     0
+(1 row)
+
+SELECT power(float8 '0', float8 '-inf');
+ERROR:  zero raised to a negative power is undefined
+SELECT power(float8 '1', float8 'inf');
+ power 
+-------
+     1
+(1 row)
+
+SELECT power(float8 '1', float8 '-inf');
+ power 
+-------
+     1
+(1 row)
+
+SELECT power(float8 '-1', float8 'inf');
+ power 
+-------
+     1
+(1 row)
+
+SELECT power(float8 '-1', float8 '-inf');
+ power 
+-------
+     1
+(1 row)
+
+SELECT power(float8 '0.1', float8 'inf');
+ power 
+-------
+     0
+(1 row)
+
+SELECT power(float8 '-0.1', float8 'inf');
+ power 
+-------
+     0
+(1 row)
+
+SELECT power(float8 '1.1', float8 'inf');
+  power   
+----------
+ Infinity
+(1 row)
+
+SELECT power(float8 '-1.1', float8 'inf');
+  power   
+----------
+ Infinity
+(1 row)
+
+SELECT power(float8 '0.1', float8 '-inf');
+  power   
+----------
+ Infinity
+(1 row)
+
+SELECT power(float8 '-0.1', float8 '-inf');
+  power   
+----------
+ Infinity
+(1 row)
+
+SELECT power(float8 '1.1', float8 '-inf');
+ power 
+-------
+     0
+(1 row)
+
+SELECT power(float8 '-1.1', float8 '-inf');
+ power 
+-------
+     0
+(1 row)
+
+SELECT power(float8 'inf', float8 '-2');
+ power 
+-------
+     0
+(1 row)
+
+SELECT power(float8 'inf', float8 '2');
+  power   
+----------
+ Infinity
+(1 row)
+
+SELECT power(float8 'inf', float8 'inf');
+  power   
+----------
+ Infinity
+(1 row)
+
+SELECT power(float8 'inf', float8 '-inf');
+ power 
+-------
+     0
+(1 row)
+
+SELECT power(float8 '-inf', float8 '-2');
+ power 
+-------
+     0
+(1 row)
+
+SELECT power(float8 '-inf', float8 '-3');
+ power 
+-------
+    -0
+(1 row)
+
+SELECT power(float8 '-inf', float8 '2');
+  power   
+----------
+ Infinity
+(1 row)
+
+SELECT power(float8 '-inf', float8 '3');
+   power   
+-----------
+ -Infinity
+(1 row)
+
+SELECT power(float8 '-inf', float8 'inf');
+  power   
+----------
+ Infinity
+(1 row)
+
+SELECT power(float8 '-inf', float8 '-inf');
+ power 
+-------
+     0
+(1 row)
+
 -- take exp of ln(f.f1)
 SELECT '' AS three, f.f1, exp(ln(f.f1)) AS exp_ln_f1
    FROM FLOAT8_TBL f
@@ -396,6 +548,13 @@ SELECT '' AS three, f.f1, exp(ln(f.f1)) AS exp_ln_f1
        | 1.2345678901234e-200 | 1.23456789012339e-200
 (3 rows)
 
+-- check edge cases for exp
+SELECT exp('inf'::float8), exp('-inf'::float8), exp('nan'::float8);
+   exp    | exp | exp 
+----------+-----+-----
+ Infinity |   0 | NaN
+(1 row)
+
 -- cube root
 SELECT ||/ float8 '27' AS three;
  three 
diff --git a/src/test/regress/sql/float8.sql b/src/test/regress/sql/float8.sql
index e540f03b07..3a8c737fb2 100644
--- a/src/test/regress/sql/float8.sql
+++ b/src/test/regress/sql/float8.sql
@@ -120,12 +120,41 @@ SELECT power(float8 'NaN', float8 'NaN');
 SELECT power(float8 '-1', float8 'NaN');
 SELECT power(float8 '1', float8 'NaN');
 SELECT power(float8 'NaN', float8 '0');
+SELECT power(float8 'inf', float8 '0');
+SELECT power(float8 '-inf', float8 '0');
+SELECT power(float8 '0', float8 'inf');
+SELECT power(float8 '0', float8 '-inf');
+SELECT power(float8 '1', float8 'inf');
+SELECT power(float8 '1', float8 '-inf');
+SELECT power(float8 '-1', float8 'inf');
+SELECT power(float8 '-1', float8 '-inf');
+SELECT power(float8 '0.1', float8 'inf');
+SELECT power(float8 '-0.1', float8 'inf');
+SELECT power(float8 '1.1', float8 'inf');
+SELECT power(float8 '-1.1', float8 'inf');
+SELECT power(float8 '0.1', float8 '-inf');
+SELECT power(float8 '-0.1', float8 '-inf');
+SELECT power(float8 '1.1', float8 '-inf');
+SELECT power(float8 '-1.1', float8 '-inf');
+SELECT power(float8 'inf', float8 '-2');
+SELECT power(float8 'inf', float8 '2');
+SELECT power(float8 'inf', float8 'inf');
+SELECT power(float8 'inf', float8 '-inf');
+SELECT power(float8 '-inf', float8 '-2');
+SELECT power(float8 '-inf', float8 '-3');
+SELECT power(float8 '-inf', float8 '2');
+SELECT power(float8 '-inf', float8 '3');
+SELECT power(float8 '-inf', float8 'inf');
+SELECT power(float8 '-inf', float8 '-inf');
 
 -- take exp of ln(f.f1)
 SELECT '' AS three, f.f1, exp(ln(f.f1)) AS exp_ln_f1
    FROM FLOAT8_TBL f
    WHERE f.f1 > '0.0';
 
+-- check edge cases for exp
+SELECT exp('inf'::float8), exp('-inf'::float8), exp('nan'::float8);
+
 -- cube root
 SELECT ||/ float8 '27' AS three;
 
