diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result
index f8737d8082b..fd1b0a1bb86 100644
--- a/mysql-test/r/analyse.result
+++ b/mysql-test/r/analyse.result
@@ -134,3 +134,16 @@ test.t1.product	Computer	TV	2	8	0	0	4.2500	NULL	ENUM('Computer','Phone','TV') NO
 sum(profit)	10	6900	2	4	0	0	1946	2868	ENUM('10','275','600','6900') NOT NULL
 avg(profit)	10.0000	1380.0000	7	9	0	0	394.6875	570.2003	ENUM('10.0000','68.7500','120.0000','1380.0000') NOT NULL
 drop table t1,t2;
+create table t1 (f1 double(10,5), f2 char(10), f3 double(10,5));
+insert into t1 values (5.999, "5.9999", 5.99999), (9.555, "9.5555", 9.55555);
+select f1 from t1 procedure analyse(1, 1);
+Field_name	Min_value	Max_value	Min_length	Max_length	Empties_or_zeros	Nulls	Avg_value_or_avg_length	Std	Optimal_fieldtype
+test.t1.f1	5.99900	9.55500	7	7	0	0	7.77700	1.77800	FLOAT(4,3) NOT NULL
+select f2 from t1 procedure analyse(1, 1);
+Field_name	Min_value	Max_value	Min_length	Max_length	Empties_or_zeros	Nulls	Avg_value_or_avg_length	Std	Optimal_fieldtype
+test.t1.f2	5.9999	9.5555	6	6	0	0	6.0000	NULL	FLOAT(5,4) UNSIGNED NOT NULL
+select f3 from t1 procedure analyse(1, 1);
+Field_name	Min_value	Max_value	Min_length	Max_length	Empties_or_zeros	Nulls	Avg_value_or_avg_length	Std	Optimal_fieldtype
+test.t1.f3	5.99999	9.55555	7	7	0	0	7.77777	1.77778	FLOAT(6,5) NOT NULL
+drop table t1;
+End of 4.1 tests
diff --git a/mysql-test/t/analyse.test b/mysql-test/t/analyse.test
index dfca8f575a4..88fe8dc55e7 100644
--- a/mysql-test/t/analyse.test
+++ b/mysql-test/t/analyse.test
@@ -82,4 +82,16 @@ create table t2 (country_id int primary key, country char(20) not null);
 insert into t2 values (1, 'USA'),(2,'India'), (3,'Finland');
 select product, sum(profit),avg(profit) from t1 group by product with rollup procedure analyse();
 drop table t1,t2;
-# End of 4.1 tests
+
+#
+# Bug #20305 PROCEDURE ANALYSE() returns wrong M for FLOAT(M, D) and DOUBLE(M, D)
+#
+
+create table t1 (f1 double(10,5), f2 char(10), f3 double(10,5));
+insert into t1 values (5.999, "5.9999", 5.99999), (9.555, "9.5555", 9.55555);
+select f1 from t1 procedure analyse(1, 1);
+select f2 from t1 procedure analyse(1, 1);
+select f3 from t1 procedure analyse(1, 1);
+drop table t1;
+
+--echo End of 4.1 tests
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index d2237c24139..3420368a026 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -709,9 +709,9 @@ void field_str::get_opt_type(String *answer, ha_rows total_rows)
     else if (num_info.decimals) // DOUBLE(%d,%d) sometime
     {
       if (num_info.dval > -FLT_MAX && num_info.dval < FLT_MAX)
-	sprintf(buff, "FLOAT(%d,%d)", num_info.integers, num_info.decimals);
+	sprintf(buff, "FLOAT(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals);
       else
-	sprintf(buff, "DOUBLE(%d,%d)", num_info.integers, num_info.decimals);
+	sprintf(buff, "DOUBLE(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals);
     }
     else if (ev_num_info.llval >= -128 &&
 	     ev_num_info.ullval <=
@@ -818,10 +818,10 @@ void field_real::get_opt_type(String *answer,
   else
   {
     if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX)
-      sprintf(buff, "FLOAT(%d,%d)", (int) max_length - (item->decimals + 1),
+      sprintf(buff, "FLOAT(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len,
 	      max_notzero_dec_len);
     else
-      sprintf(buff, "DOUBLE(%d,%d)", (int) max_length - (item->decimals + 1),
+      sprintf(buff, "DOUBLE(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len,
 	      max_notzero_dec_len);
     answer->append(buff, (uint) strlen(buff));
   }