Merge 64438: hex/oct/bin can show floats exactly.
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 60a5e84..0d40d17 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -1451,8 +1451,11 @@
 PyNumber_ToBase(PyObject *n, int base)
 {
 	PyObject *res = NULL;
-	PyObject *index = PyNumber_Index(n);
+	PyObject *index;
 
+	if (PyFloat_Check(n))
+		return _float_to_base(n, base);
+	index = PyNumber_Index(n);
 	if (!index)
 		return NULL;
 	if (PyLong_Check(index))
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index db1c99f..2465fa9 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -1113,6 +1113,36 @@
 ">>> (-.25).as_integer_ratio()\n"
 "(-1, 4)");
 
+PyObject *
+_float_to_base(PyObject *v, int base)
+{
+	PyObject *mant, *conv, *result;
+	double x, fr;
+	int i, exp;
+
+	if (!PyFloat_Check(v)) {
+		PyErr_BadInternalCall();
+		return NULL;
+	}
+	CONVERT_TO_DOUBLE(v, x);
+	if (!Py_IS_FINITE(x))
+		return PyObject_Repr(v);
+	fr = frexp(x, &exp);
+	for (i=0; i<300 && fr != floor(fr) ; i++) {
+		fr *= 2.0;
+		exp--;
+	}
+	mant = PyLong_FromDouble(floor(fr));
+	if (mant == NULL)
+		return NULL;
+	conv = PyNumber_ToBase(mant, base);
+	Py_DECREF(mant);
+	if (conv == NULL)
+		return NULL;
+	result = PyUnicode_FromFormat("%U * 2.0 ** %d", conv, exp);
+	Py_DECREF(conv);
+	return result;
+}
 
 static PyObject *
 float_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);