Frage

Ich habe eine C-Funktion, die eine long double zurückgibt. Ich möchte diese Funktion von Python nennen ctypes verwenden, und es funktioniert meistens. so.func.restype = c_longdouble Einstellung funktioniert der Trick - außer, dass Schwimmer Typ der Python ein c_double ist also, wenn der zurückgegebene Wert größer als ein Doppelzimmer, aber auch innerhalb der Grenzen eines langen Doppel, Python wird nach wie vor als Rückgabewert inf. ich bin auf einem 64-Bit-Prozessor und sizeof(long double) ist 16.

irgendwelche Ideen auf, um diese bekommen (zum Beispiel der Dezimalzahl Klasse oder numpy verwendet wird), ohne den C-Code zu modifizieren?

War es hilfreich?

Lösung

Ich bin mir nicht sicher, dass Sie es ohne Änderung des C-Code tun. ctypes scheint für long doubles wirklich schlechte Unterstützung zu haben -. Sie sie wie Zahlen gar nicht manipulieren kann, alles, was Sie tun können, sie ist konvertieren hin und her zwischen dem nativen float Python Typ

Sie können auch nicht ein Byte-Array als Rückgabewert anstelle eines c_longdouble, wegen der ABI - Gleitkommawerte sind nicht im %eax Register oder auf dem Stapel wie normale Rückgabewerte zurück, sie sind ging durch die hardwarespezifischen Gleitkommaregister.

Andere Tipps

Wenn Sie eine Funktion haben zurückgeben Unterklasse von c_longdouble, wird es die ctypes zurückkehren Objekt gewickelt Feld anstatt auf eine Python float konvertieren. Sie können dann den Bytes aus diesem Extrakt (mit memcpy in eine c_char Array, zum Beispiel) oder das Objekt zu einer anderen C-Funktion zur Weiterverarbeitung übergeben. Die snprintf Funktion kann es formatiert werden in einen String für den Druck oder die Umwandlung in eine hochpräzise Python numerischen Typ.

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)

Ausgabe:

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

(Beachten Sie, dass meine Schätzung von 35 Stellen genau zu stark für optimistisch entpuppte long double Berechnungen auf Intel-Prozessoren, die nur 64 Bit Mantisse haben. Sie sollten %a verwenden, anstatt %e / f / g wenn Sie zu konvertieren beabsichtigen zu einem Format, das auf Dezimaldarstellung basiert.)

Wenn Sie benötigen hochgenaue Punkt schweben, haben einen Blick auf GMPY.

GMPY ist ein C-codierte Python-Erweiterungsmodul, das die GMP-Bibliothek wickelt bereitzustellen zu Python-Code schnell mehrfach Arithmetik (integer, rational, und float), Erzeugung von Zufallszahlen, erweitern zahlentheoretischen Funktionen und vieles mehr.

GMP enthält High-Level-Floating-Point-Rechenfunktionen (mpf). Dies ist die GMP-Funktion Kategorie zu verwenden, wenn der C-Typ `double‘ nicht genug Präzision für eine Anwendung geben. Es gibt etwa 65 Funktionen in dieser Kategorie.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top