2013-04-06 16 views
8

Bizzarely, każda funkcja z modułu matematycznego Pythona wydaje się działać dobrze z obiektami dziesiętnymi. Na przykład: frexp, exp, cos.Python: dlaczego funkcje w module matematyki akceptują obiekty dziesiętne jako argumenty?

Po wpisaniu print(math.frexp(decimal.Decimal('2341.12412'))), Python drukuje poprawną odpowiedź, która jest (0.57156... , 12) i nie rzuca żadnych wyjątków.

Zakładam, że moduł matematyczny zostałby napisany na niskim poziomie C, polegając na operacjach matematycznych ze względów sprzętowych, aby uzyskać większą wydajność. Więc ... dlaczego to działa dla obiektów dziesiętnych?

Czy wprowadzono sprawdzenie typu do funkcji matematycznych i przełączono do innej implementacji, jeśli argument ma wartość dziesiętną? Nie widziałem czegoś podobnego w dokumentach. Możliwe też, że dziesiętny jest automatycznie konwertowany na zmienną, ale to też nie ma sensu.

Tak, jestem zdezorientowany.

+2

Przede wszystkim są one konwertowane na zmienne. – Antimony

+0

Rozszerz funkcje obiektu "Dziesiętny" i zobacz, co jest na nim wywoływane, kiedy go przekażesz. –

+0

Po prostu próbowałem tego teraz. Rozszerzyłem klasę dziesiętną i przesłoniłem funkcje \ _ \ _ add__ i \ _ \ _ multiply__, aby wydrukować wiadomość i wywołać równoważną funkcję dziesiętną. Do tej pory wygląda na to, że żadna z funkcji matematycznych nie wywołuje ___ _ _ add__ lub \ _ \ _ multiply__, ponieważ wiadomości nie są drukowane, gdy je wywołuję (exp, frexp itp.). Prawdopodobnie liczba dziesiętna jest konwertowana na wartość zmiennoprzecinkową ... –

Odpowiedz

7

Dobrze patrząc na math module.c mam to:

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

Patrząc na kod, to jednak w rzeczywistości korzystać float (PyFloat_AsDouble)

Znowu to samo dla 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

Dzięki! Jestem naprawdę zaskoczony, że zamieniliby argument na float. Pomyślałbym, że lepiej byłoby, gdyby programista sam dokonał konwersji ... ale co ja wiem? –

Powiązane problemy