2013-04-06 12 views
8

Sinceramente, ogni funzione del modulo matematico di Python sembra funzionare perfettamente con gli oggetti decimali. Ad esempio: frexp, exp, cos.Python: perché le funzioni nel modulo matematico accettano gli oggetti decimali come argomenti?

Quando si digita print(math.frexp(decimal.Decimal('2341.12412'))), Python stampa la risposta corretta, ovvero (0.57156... , 12), e non genera eccezioni.

Suppongo che il modulo matematico venga scritto in C di basso livello, facendo affidamento il più possibile sulle operazioni matematiche hardware per l'efficienza. Quindi ... perché dovrebbe funzionare per gli oggetti decimali?

Hanno inserito un controllo di tipo nelle funzioni matematiche e passare a un'implementazione diversa se l'argomento è un decimale? Non ho visto nulla di simile menzionato nei documenti. Potrebbe anche essere che il decimale viene automaticamente convertito in un float, ma anche questo non ha alcun senso.

Sì, sono confuso.

+2

Presuambly, sono stati convertiti in galleggianti. – Antimony

+0

Estendere le funzioni dell'oggetto 'Decimale' e vedere cosa viene chiamato quando lo si passa. –

+0

L'ho appena provato. Ho esteso la classe Decimal e ho annullato le funzioni \ _ \ _ add__ e \ _ \ _ multiply__ per stampare un messaggio e chiamare la funzione decimale equivalente. Finora, sembra che nessuna delle funzioni matematiche stia chiamando \ _ \ _ add__ o \ _ \ _ multiply__, perché i messaggi non vengono stampati quando li chiamo (exp, frexp, ecc.). Probabilmente il Decimale viene convertito in un float ... –

risposta

7

Bene guardando il math module.c ho ottenuto questo:

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); 
} 

Guardando il codice, lo fa in realtà usa float (PyFloat_AsDouble)

Sempre stessa cosa per 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

Grazie! Sono sinceramente sorpreso che convertissero l'argomento in un float. Avrei pensato che sarebbe stato meglio lasciare che il programmatore effettuasse la conversione da solo ... ma cosa ne so? –

Problemi correlati