2013-04-06 4 views
8

Bizzarely, scheint jede Funktion von Python-Mathematik-Modul gut mit Dezimal-Objekten funktionieren. Zum Beispiel: frexp, exp, cos. Wenn ich print(math.frexp(decimal.Decimal('2341.12412'))) tippe, druckt Python die richtige Antwort, die (0.57156... , 12) ist, und wirft keine Ausnahmen.Python: Warum akzeptieren Funktionen im Mathematikmodul Dezimalobjekte als Argumente?

Ich würde annehmen, dass das Mathematik-Modul in Low-Level-C geschrieben werden würde, so stark wie möglich auf Hardware-Mathematik-Operationen für die Effizienz verlassen. Also ... warum würde es für Dezimalobjekte funktionieren?

Haben sie eine Typprüfung in die mathematischen Funktionen eingefügt und wechseln zu einer anderen Implementierung, wenn das Argument ein Dezimalzeichen ist? So etwas habe ich in den Unterlagen nicht gesehen. Es könnte auch sein, dass das Dezimale automatisch in einen Float umgewandelt wird, aber das macht auch keinen Sinn.

Ja, ich bin verwirrt.

+2

Zuvor werden sie zu Schwimmern umgebaut. – Antimony

+0

Erweitern Sie die Funktionen des "Decimal" -Objekts und sehen Sie, wie es aufgerufen wird, wenn Sie es übergeben. –

+0

Ich habe das gerade jetzt versucht. Ich habe die Decimal-Klasse erweitert und die Funktionen \ _ \ _ add__ und \ _ \ _multiple__ überschrieben, um eine Nachricht zu drucken und die entsprechende Dezimalfunktion aufzurufen. Bisher scheint es so, als ob keine der mathematischen Funktionen \ _ \ _ add__ oder \ _ \ _ multiply__ aufruft, weil die Nachrichten nicht gedruckt werden, wenn ich sie anrufe (exp, frexp, etc). Wahrscheinlich wird die Dezimalzahl in eine Gleitkommazahl umgewandelt ... –

Antwort

7

Nun am math module.c suchen habe ich dieses:

static PyObject * 
math_frexp(PyObject *self, PyObject *arg) 
{ 
    int i; 
    double x = PyFloat_AsDouble(arg); 
    if (x == -1.0 && PyErr_Occurred()) 
     return NULL; 
    /* deal with special cases directly, to sidestep platform 
     differences */ 
    if (Py_IS_NAN(x) || Py_IS_INFINITY(x) || !x) { 
     i = 0; 
    } 
    else { 
     PyFPE_START_PROTECT("in math_frexp", return 0); 
     x = frexp(x, &i); 
     PyFPE_END_PROTECT(x); 
    } 
    return Py_BuildValue("(di)", x, i); 
} 

auf den Code der Suche, ist es in der Tat verwenden float (PyFloat_AsDouble)

Wieder gleiche Sache für exp,

static PyObject * 
math_factorial(PyObject *self, PyObject *arg) 
{ 
    long x; 
    PyObject *result, *odd_part, *two_valuation; 

    if (PyFloat_Check(arg)) { 
     PyObject *lx; 
     double dx = PyFloat_AS_DOUBLE((PyFloatObject *)arg); 
     if (!(Py_IS_FINITE(dx) && dx == floor(dx))) { 
      PyErr_SetString(PyExc_ValueError, 
          "factorial() only accepts integral values"); 
      return NULL; 
     } 
     lx = PyLong_FromDouble(dx); 
     if (lx == NULL) 
      return NULL; 
     x = PyLong_AsLong(lx); 
     Py_DECREF(lx); 
......................................................... 
+0

Danke! Ich bin ehrlich überrascht, dass sie das Argument in einen Float verwandeln würden. Ich hätte gedacht, es wäre besser, wenn der Programmierer die Konvertierung selbst machen würde ... aber was weiß ich? –

Verwandte Themen