diff --git a/doc/src/sgml/plpython.sgml b/doc/src/sgml/plpython.sgml
index aaf758d..7e55b75 100644
--- a/doc/src/sgml/plpython.sgml
+++ b/doc/src/sgml/plpython.sgml
@@ -312,10 +312,8 @@ $$ LANGUAGE plpythonu;
       <para>
        PostgreSQL <type>real</type>, <type>double</type>,
        and <type>numeric</type> are converted to
-       Python <type>float</type>.  Note that for
-       the <type>numeric</type> this loses information and can lead to
-       incorrect results.  This might be fixed in a future
-       release.
+       Python <type>Decimal</type>. This type is imported from
+       <literal>decimal.Decimal</literal>.
       </para>
      </listitem>
 
diff --git a/src/pl/plpython/expected/plpython_types.out b/src/pl/plpython/expected/plpython_types.out
index 4641345..2c4bb6a 100644
--- a/src/pl/plpython/expected/plpython_types.out
+++ b/src/pl/plpython/expected/plpython_types.out
@@ -216,31 +216,39 @@ CREATE FUNCTION test_type_conversion_numeric(x numeric) RETURNS numeric AS $$
 plpy.info(x, type(x))
 return x
 $$ LANGUAGE plpythonu;
-/* The current implementation converts numeric to float. */
+/* The current implementation converts numeric to decimal.Decimal. */
 SELECT * FROM test_type_conversion_numeric(100);
-INFO:  (100.0, <type 'float'>)
+INFO:  (Decimal('100'), <class 'decimal.Decimal'>)
 CONTEXT:  PL/Python function "test_type_conversion_numeric"
  test_type_conversion_numeric 
 ------------------------------
-                        100.0
+                          100
 (1 row)
 
 SELECT * FROM test_type_conversion_numeric(-100);
-INFO:  (-100.0, <type 'float'>)
+INFO:  (Decimal('-100'), <class 'decimal.Decimal'>)
 CONTEXT:  PL/Python function "test_type_conversion_numeric"
  test_type_conversion_numeric 
 ------------------------------
-                       -100.0
+                         -100
 (1 row)
 
 SELECT * FROM test_type_conversion_numeric(5000000000.5);
-INFO:  (5000000000.5, <type 'float'>)
+INFO:  (Decimal('5000000000.5'), <class 'decimal.Decimal'>)
 CONTEXT:  PL/Python function "test_type_conversion_numeric"
  test_type_conversion_numeric 
 ------------------------------
                  5000000000.5
 (1 row)
 
+SELECT * FROM test_type_conversion_numeric(1234567890.0987654321);
+INFO:  (Decimal('1234567890.0987654321'), <class 'decimal.Decimal'>)
+CONTEXT:  PL/Python function "test_type_conversion_numeric"
+ test_type_conversion_numeric 
+------------------------------
+        1234567890.0987654321
+(1 row)
+
 SELECT * FROM test_type_conversion_numeric(null);
 INFO:  (None, <type 'NoneType'>)
 CONTEXT:  PL/Python function "test_type_conversion_numeric"
diff --git a/src/pl/plpython/plpy_main.c b/src/pl/plpython/plpy_main.c
index 0dad843..ffce97d 100644
--- a/src/pl/plpython/plpy_main.c
+++ b/src/pl/plpython/plpy_main.c
@@ -77,6 +77,9 @@ static const int plpython_python_version = PY_MAJOR_VERSION;
 /* initialize global variables */
 PyObject   *PLy_interp_globals = NULL;
 
+/* global pointer to decimal.Decimal costructor */
+PyObject   *PLy_decimal_ctor_global = NULL;
+
 /* this doesn't need to be global; use PLy_current_execution_context() */
 static PLyExecutionContext *PLy_execution_contexts = NULL;
 
@@ -147,9 +150,23 @@ PLy_init_interp(void)
 	if (PLy_interp_safe_globals == NULL)
 		PLy_elog(ERROR, "could not create globals");
 	PyDict_SetItemString(PLy_interp_globals, "GD", PLy_interp_safe_globals);
-	Py_DECREF(mainmod);
+
 	if (PLy_interp_globals == NULL || PyErr_Occurred())
 		PLy_elog(ERROR, "could not initialize globals");
+
+	PyObject *decimal = PyImport_ImportModule("decimal");
+	if (decimal == NULL)
+		PLy_elog(ERROR, "could not import module 'decimal'");
+
+	PyObject *decimal_dict = PyModule_GetDict(decimal);
+	if (decimal_dict == NULL)
+		PLy_elog(ERROR, "could not get decimal dict from imported module");
+
+	PLy_decimal_ctor_global = PyDict_GetItemString(decimal_dict, "Decimal");
+	if (PLy_decimal_ctor_global == NULL || !PyCallable_Check(PLy_decimal_ctor_global))
+		PLy_elog(ERROR, "could not get decimal consctructor for Decimal type");
+
+	Py_DECREF(mainmod);
 }
 
 Datum
diff --git a/src/pl/plpython/plpy_typeio.c b/src/pl/plpython/plpy_typeio.c
index 8f2367d..83e0e50 100644
--- a/src/pl/plpython/plpy_typeio.c
+++ b/src/pl/plpython/plpy_typeio.c
@@ -18,6 +18,7 @@
 #include "utils/memutils.h"
 #include "utils/syscache.h"
 #include "utils/typcache.h"
+#include "utils/numeric.h"
 
 #include "plpython.h"
 
@@ -26,6 +27,7 @@
 #include "plpy_elog.h"
 #include "plpy_main.h"
 
+extern PyObject *PLy_decimal_ctor_global;
 
 /* I/O function caching */
 static void PLy_input_datum_func2(PLyDatumToOb *arg, Oid typeOid, HeapTuple typeTup);
@@ -35,7 +37,7 @@ static void PLy_output_datum_func2(PLyObToDatum *arg, HeapTuple typeTup);
 static PyObject *PLyBool_FromBool(PLyDatumToOb *arg, Datum d);
 static PyObject *PLyFloat_FromFloat4(PLyDatumToOb *arg, Datum d);
 static PyObject *PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d);
-static PyObject *PLyFloat_FromNumeric(PLyDatumToOb *arg, Datum d);
+static PyObject *PLyDecimal_FromNumeric(PLyDatumToOb *arg, Datum d);
 static PyObject *PLyInt_FromInt16(PLyDatumToOb *arg, Datum d);
 static PyObject *PLyInt_FromInt32(PLyDatumToOb *arg, Datum d);
 static PyObject *PLyLong_FromInt64(PLyDatumToOb *arg, Datum d);
@@ -450,7 +452,7 @@ PLy_input_datum_func2(PLyDatumToOb *arg, Oid typeOid, HeapTuple typeTup)
 			arg->func = PLyFloat_FromFloat8;
 			break;
 		case NUMERICOID:
-			arg->func = PLyFloat_FromNumeric;
+			arg->func = PLyDecimal_FromNumeric;
 			break;
 		case INT2OID:
 			arg->func = PLyInt_FromInt16;
@@ -516,16 +518,12 @@ PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d)
 }
 
 static PyObject *
-PLyFloat_FromNumeric(PLyDatumToOb *arg, Datum d)
+PLyDecimal_FromNumeric(PLyDatumToOb *arg, Datum d)
 {
-	/*
-	 * Numeric is cast to a PyFloat: This results in a loss of precision Would
-	 * it be better to cast to PyString?
-	 */
-	Datum		f = DirectFunctionCall1(numeric_float8, d);
-	double		x = DatumGetFloat8(f);
-
-	return PyFloat_FromDouble(x);
+	char *x = DatumGetCString(DirectFunctionCall1(numeric_out, d));
+	PyObject *pvalue = PyString_FromString(x);
+	PyObject *value = PyObject_CallFunctionObjArgs(PLy_decimal_ctor_global, pvalue, NULL);
+	return value;
 }
 
 static PyObject *
diff --git a/src/pl/plpython/sql/plpython_types.sql b/src/pl/plpython/sql/plpython_types.sql
index 6a50b42..e35421f 100644
--- a/src/pl/plpython/sql/plpython_types.sql
+++ b/src/pl/plpython/sql/plpython_types.sql
@@ -90,10 +90,11 @@ plpy.info(x, type(x))
 return x
 $$ LANGUAGE plpythonu;
 
-/* The current implementation converts numeric to float. */
+/* The current implementation converts numeric to decimal.Decimal. */
 SELECT * FROM test_type_conversion_numeric(100);
 SELECT * FROM test_type_conversion_numeric(-100);
 SELECT * FROM test_type_conversion_numeric(5000000000.5);
+SELECT * FROM test_type_conversion_numeric(1234567890.0987654321);
 SELECT * FROM test_type_conversion_numeric(null);
 
 
