2013-04-06 29 views
8

Bizzarely, mọi chức năng từ mô-đun toán học của Python dường như hoạt động tốt với các đối tượng thập phân. Ví dụ: frexp, exp, cos.Python: tại sao các hàm trong mô-đun toán học chấp nhận các đối tượng thập phân làm đối số?

Khi tôi nhập print(math.frexp(decimal.Decimal('2341.12412'))), Python in câu trả lời chính xác, là (0.57156... , 12) và không ném bất kỳ ngoại lệ nào.

Tôi giả định rằng mô-đun toán học sẽ được viết ở cấp độ C thấp, dựa nhiều nhất có thể vào hoạt động toán phần cứng để đạt hiệu quả. Vì vậy, ... tại sao nó sẽ làm việc cho các đối tượng thập phân?

Họ đã đặt kiểm tra loại vào các hàm toán học và chuyển sang triển khai khác nếu đối số là một số thập phân? Tôi không thấy bất cứ điều gì như thế được đề cập trong tài liệu. Nó cũng có thể là Thập phân được tự động chuyển đổi thành một phao, nhưng điều đó cũng không có ý nghĩa gì cả.

Vâng, tôi đang bối rối.

+2

Presuambly, họ đang được chuyển đổi để nổi. – Antimony

+0

Mở rộng các chức năng của đối tượng 'thập phân' và xem những gì đang được gọi trên nó khi bạn truyền nó vào. –

+0

Tôi vừa thử điều đó ngay bây giờ. Tôi mở rộng lớp Decimal và overrode các chức năng \ _ \ _ add__ và \ _ \ _ multiply__ để in một tin nhắn và gọi hàm thập phân tương đương. Cho đến nay, có vẻ như không có hàm toán học nào gọi \ _ \ _ add__ hoặc \ _ \ _ multiply__, bởi vì các thông điệp không in khi tôi gọi chúng (exp, frexp, v.v.). Có lẽ thập phân đang được chuyển đổi thành một phao ... –

Trả lời

7

Vâng nhìn vào math module.c Tôi nhận điều này:

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

Nhìn vào mã này, nó trong thực tế sử dụng float (PyFloat_AsDouble)

Một lần nữa điều tương tự cho 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

Cảm ơn! Tôi thành thật ngạc nhiên rằng họ sẽ chuyển đổi đối số thành một phao. Tôi đã nghĩ sẽ tốt hơn nếu để cho lập trình viên tự biến đổi ... nhưng tôi biết điều gì? –

Các vấn đề liên quan