diff --git a/doc/src/sgml/plpython.sgml b/doc/src/sgml/plpython.sgml
index aaf758d..da27874 100644
--- a/doc/src/sgml/plpython.sgml
+++ b/doc/src/sgml/plpython.sgml
@@ -308,14 +308,19 @@ $$ LANGUAGE plpythonu;
       </para>
      </listitem>
 
+	 <listitem>
+      <para>
+       PostgreSQL <type>real</type> and <type>double</type> are converted to
+       Python <type>float</type>.
+      </para>
+     </listitem>
+
      <listitem>
       <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.
+       PostgreSQL <type>numeric</type> is converted to
+       Python <type>Decimal</type>. This type is imported from 
+	   <literal>cdecimal</literal> package if it is available. If cdecimal
+	   cannot be used, then <literal>decimal.Decimal</literal> will be used.
       </para>
      </listitem>
 
diff --git a/src/pl/plpython/expected/plpython_types.out b/src/pl/plpython/expected/plpython_types.out
index 4641345..1742114 100644
--- a/src/pl/plpython/expected/plpython_types.out
+++ b/src/pl/plpython/expected/plpython_types.out
@@ -213,36 +213,52 @@ CONTEXT:  PL/Python function "test_type_conversion_int8"
 (1 row)
 
 CREATE FUNCTION test_type_conversion_numeric(x numeric) RETURNS numeric AS $$
-plpy.info(x, type(x))
+plpy.info(x.__class__.__name__)
 return x
 $$ LANGUAGE plpythonu;
-/* The current implementation converts numeric to float. */
+/* The current implementation converts numeric to Decimal. */
 SELECT * FROM test_type_conversion_numeric(100);
-INFO:  (100.0, <type 'float'>)
+INFO:  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
 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
 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
+CONTEXT:  PL/Python function "test_type_conversion_numeric"
+ test_type_conversion_numeric 
+------------------------------
+        1234567890.0987654321
+(1 row)
+
+SELECT * FROM test_type_conversion_numeric(-1234567890.0987654321);
+INFO:  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'>)
+INFO:  NoneType
 CONTEXT:  PL/Python function "test_type_conversion_numeric"
  test_type_conversion_numeric 
 ------------------------------
diff --git a/src/pl/plpython/expected/plpython_types_3.out b/src/pl/plpython/expected/plpython_types_3.out
index 511ef5a..57538b3 100644
--- a/src/pl/plpython/expected/plpython_types_3.out
+++ b/src/pl/plpython/expected/plpython_types_3.out
@@ -213,36 +213,52 @@ CONTEXT:  PL/Python function "test_type_conversion_int8"
 (1 row)
 
 CREATE FUNCTION test_type_conversion_numeric(x numeric) RETURNS numeric AS $$
-plpy.info(x, type(x))
+plpy.info(str(x))
 return x
 $$ LANGUAGE plpython3u;
-/* The current implementation converts numeric to float. */
+/* The current implementation converts numeric to Decimal. */
 SELECT * FROM test_type_conversion_numeric(100);
-INFO:  (100.0, <class 'float'>)
+INFO:  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, <class 'float'>)
+INFO:  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, <class 'float'>)
+INFO:  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
+CONTEXT:  PL/Python function "test_type_conversion_numeric"
+ test_type_conversion_numeric 
+------------------------------
+        1234567890.0987654321
+(1 row)
+
+SELECT * FROM test_type_conversion_numeric(-1234567890.0987654321);
+INFO:  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, <class 'NoneType'>)
+INFO:  NoneType
 CONTEXT:  PL/Python function "test_type_conversion_numeric"
  test_type_conversion_numeric 
 ------------------------------
diff --git a/src/pl/plpython/plpy_typeio.c b/src/pl/plpython/plpy_typeio.c
index 6a9a2cb..e04c2f9 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"
 
@@ -35,7 +36,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 +451,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 +517,33 @@ 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);
+	char *x;
+	PyObject *pvalue, *value, *decimal, *decimal_dict;
+	static PyObject *decimal_ctor;
+
+	/* Try to import cdecimal, if it doesnt exist, fallback to decimal */
+	if (decimal_ctor == NULL)
+	{
+		decimal = PyImport_ImportModule("cdecimal");
+		if (decimal == NULL)
+		{
+			PyErr_Clear();
+			decimal = PyImport_ImportModule("decimal");
+		}
+		if (decimal == NULL)
+			PLy_elog(ERROR, "could not import module 'decimal'");
+
+		decimal_dict = PyModule_GetDict(decimal);
+		decimal_ctor = PyDict_GetItemString(decimal_dict, "Decimal");
+		Py_DECREF(decimal_dict);
+	}
 
-	return PyFloat_FromDouble(x);
+	x = DatumGetCString(DirectFunctionCall1(numeric_out, d));
+	pvalue = PyString_FromString(x);
+	value = PyObject_CallFunctionObjArgs(decimal_ctor, 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..fd7fbca 100644
--- a/src/pl/plpython/sql/plpython_types.sql
+++ b/src/pl/plpython/sql/plpython_types.sql
@@ -86,14 +86,16 @@ SELECT * FROM test_type_conversion_int8(null);
 
 
 CREATE FUNCTION test_type_conversion_numeric(x numeric) RETURNS numeric AS $$
-plpy.info(x, type(x))
+plpy.info(x.__class__.__name__)
 return x
 $$ LANGUAGE plpythonu;
 
-/* The current implementation converts numeric to float. */
+/* The current implementation converts numeric to 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(-1234567890.0987654321);
 SELECT * FROM test_type_conversion_numeric(null);
 
 
