سؤال

ولدي وظيفة ج التي ترجع long double. أود أن استدعاء هذه الدالة من الثعبان باستخدام ctypes، وأنها تعمل في الغالب. وضع so.func.restype = c_longdouble لا حيلة - باستثناء نوع تعويم أن الثعبان هو لc_double حتى إذا القيمة التي تم إرجاعها أكبر من ضعف، ولكن أيضا في حدود طويلة مزدوج، الثعبان لا يزال يحصل على الوقود النووي المشع كقيمة الإرجاع. أنا على معالج 64 بت و sizeof(long double) هو 16.

وأي أفكار على الالتفاف حول هذا (على سبيل المثال باستخدام الفئة العشرية أو نمباي) دون تعديل التعليمات البرمجية ج؟

هل كانت مفيدة؟

المحلول

وأنا لست متأكد من أنك يمكن أن تفعل ذلك دون تعديل التعليمات البرمجية C. ctypes يبدو أن الدعم سيئة حقا لlong doubles - لا يمكن التلاعب بها مثل أرقام على الإطلاق، كل ما يمكن القيام به هو تحويلها ذهابا وإيابا بين الأصلي نوع float بيثون

ولا يمكنك حتى استخدام صفيف بايت كقيمة الإرجاع بدلا من c_longdouble، بسبب ABI - لم يتم إرجاع القيم الفاصلة العائمة في السجل %eax أو على كومة مثل قيم الإرجاع العادية، وانهم مرت سجلات الفاصلة العائمة الخاصة بالأجهزة.

نصائح أخرى

إذا كان لديك وظيفة بإرجاع <م> فئة فرعية من c_longdouble، فإنه سيعود ctypes ملفوفة كائن حقل بدلا من التحويل إلى float الثعبان. يمكنك ثم استخراج بايت من هذه (مع memcpy إلى مجموعة c_char مثلا) أو تمرير الكائن إلى وظيفة C أخرى لمزيد من المعالجة. وظيفة snprintf يمكن تهيئته إلى سلسلة للطباعة أو تحويلها إلى درجة عالية من الدقة الثعبان نوع عددي.

import ctypes
libc = ctypes.cdll['libc.so.6']
libm = ctypes.cdll['libm.so.6']

class my_longdouble(ctypes.c_longdouble):
    def __str__(self):
        size = 100
        buf = (ctypes.c_char * size)()
        libc.snprintf(buf, size, '%.35Le', self)
        return buf[:].rstrip('\0')

powl = libm.powl
powl.restype = my_longdouble
powl.argtypes = [ctypes.c_longdouble, ctypes.c_longdouble]

for i in range(1020,1030):
    res = powl(2,i)
    print '2**'+str(i), '=', str(res)

وإخراج:

2**1020 = 1.12355820928894744233081574424314046e+307
2**1021 = 2.24711641857789488466163148848628092e+307
2**1022 = 4.49423283715578976932326297697256183e+307
2**1023 = 8.98846567431157953864652595394512367e+307
2**1024 = 1.79769313486231590772930519078902473e+308
2**1025 = 3.59538626972463181545861038157804947e+308
2**1026 = 7.19077253944926363091722076315609893e+308
2**1027 = 1.43815450788985272618344415263121979e+309
2**1028 = 2.87630901577970545236688830526243957e+309
2**1029 = 5.75261803155941090473377661052487915e+309

و(لاحظ أن تقديري من 35 أرقام من الدقة تبين أن نكون متفائلين بشكل مفرط لإجراء العمليات الحسابية long double على معالجات إنتل، التي لا تملك إلا 64 بت من العشري. يجب عليك استخدام %a بدلا من %e / f / g إذا كنت تنوي تحويل إلى تنسيق التي لا تقوم على تمثيل عشري).

إذا كنت تحتاج إلى درجة عالية من الدقة النقطة العائمة، وإلقاء نظرة على GMPY.

GMPY هو وحدة تمديد بيثون مرمزة C التي يلتف مكتبة GMP لتوفير إلى رمز بيثون الحساب سريع multiprecision (عدد صحيح ومنطقي، وتعويم)، وتوليد رقم عشوائي، وظائف عدد النظري المتقدمة، وأكثر من ذلك.

GMP يحتوي على مستوى عال الفاصلة العائمة وظائف حسابية (mpf). هذه هي الفئة ظيفة GMP لاستخدام إذا كان نوع C `ضعف 'لا يعطي ما يكفي من الدقة للتطبيق. وهناك حوالي 65 وظائف في هذه الفئة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top