質問

iには、 long double を返すc関数があります。私はctypesを使用してpythonからこの関数を呼び出したいのですが、ほとんど機能します。 so.func.restype = c_longdouble を設定するとトリックが行われます。ただし、Pythonのfloat型は c_double であるため、戻り値がdoubleよりも大きいが、 long doubleの境界、Pythonはまだ戻り値としてinfを取得します。 64ビットプロセッサを使用しており、 sizeof(long double)は16です。

cコードを変更せずにこれを回避する(たとえば、decimalクラスまたはnumpyを使用する)アイデアはありますか?

役に立ちましたか?

解決

Cコードを変更せずに実行できるかどうかはわかりません。 ctypesは long double のサポートが本当に悪いようです-数値のようにそれらを操作することはできません。できるのは、ネイティブの float Pythonタイプ。

ABIのため、戻り値として c_longdouble の代わりにバイト配列を使用することさえできません-浮動小数点値は%eax レジスタまたは通常の戻り値のようにスタック上で、ハードウェア固有の浮動小数点レジスタを介して渡されます。

他のヒント

c_longdouble サブクラスを返す関数がある場合、Python float に変換するのではなく、ctypesラップフィールドオブジェクトを返します。 。次に、これからバイトを抽出し( memcpy を使用してc_char配列などに)、オブジェクトを別のC関数に渡してさらに処理します。 snprintf 関数は、印刷または高精度のPython数値型への変換のために文字列にフォーマットできます。

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桁の精度の推定値は、64ビットの仮数しかないIntelプロセッサでの long double 計算に対して過度に楽観的であることが判明したことに注意してください。%a 10進表現に基づいていない形式に変換する場合は、%e / f / g ではなくを使用します。)

高精度の浮動小数点が必要な場合は、GMPYをご覧ください。

GMPY は、GMPライブラリをラップして提供するCコードPython拡張モジュールです。 Pythonコードへの高速多精度演算(整数、有理数、浮動小数点数)、乱数生成、高度な数論関数など。

GMP には、高レベルの浮動小数点演算関数( mpf )が含まれています。これは、Cタイプ「double」がアプリケーションに十分な精度を与えない場合に使用するGMP関数カテゴリです。このカテゴリには約65の関数があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top