diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index f4520ff3f746ccea08c4cabf2f8b6c05c514a2b6..7ea0377ec715c95711b108df6eb988b6f3b1c146 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -1490,14 +1490,23 @@ namespace __format
 	      // If the buffer is too small it's probably because of a large
 	      // precision, or a very large value in fixed format.
 	      size_t __guess = 8 + __prec;
-	      if (__fmt == chars_format::fixed && __v != 0) // +ddd.prec
+	      if (__fmt == chars_format::fixed) // +ddd.prec
 		{
-		  if constexpr (is_same_v<_Fp, float>)
-		    __guess += __builtin_log10f(__v < 0.0f ? -__v : __v);
-		  else if constexpr (is_same_v<_Fp, double>)
-		    __guess += __builtin_log10(__v < 0.0 ? -__v : __v);
-		  else if constexpr (is_same_v<_Fp, long double>)
-		    __guess += __builtin_log10l(__v < 0.0l ? -__v : __v);
+		  if constexpr (is_same_v<_Fp, float> || is_same_v<_Fp, double>
+				  || is_same_v<_Fp, long double>)
+		    {
+		      // The number of digits to the left of the decimal point
+		      // is floor(log10(max(abs(__v),1)))+1
+		      int __exp{};
+		      if constexpr (is_same_v<_Fp, float>)
+			__builtin_frexpf(__v, &__exp);
+		      else if constexpr (is_same_v<_Fp, double>)
+			__builtin_frexp(__v, &__exp);
+		      else if constexpr (is_same_v<_Fp, long double>)
+			__builtin_frexpl(__v, &__exp);
+		      if (__exp > 0)
+			__guess += 1U + __exp * 4004U / 13301U; // log10(2) approx.
+		    }
 		  else
 		    __guess += numeric_limits<_Fp>::max_exponent10;
 		}