12

C99のクワッドプレシジョンロングダブルをやってます。(プラットフォーム固有の) numpy がlong doubleと 128bit float をサポートしていることは、私の理解です。

しかし、説明できない何かに出くわしました。

与えられた:

>>> import numpy as np

整数として表すのに 64 ビット以上 128 ビット未満である数値を計算します。

>>> 2**64+2
18446744073709551618          # note the '8' at the end
>>> int(2**64+2)
18446744073709551618          # same obviously

C99 128 ビット long double で同じ数値を計算すると、次のようになります。18446744073709551618.000000

さて、numpy long double を使用すると:

>>> a=np.longdouble(2)
>>> b=np.longdouble(64)
>>> a**b+a
18446744073709551618.0              # all good...

これらの誤った結果についてはどうですか:

>>> np.longdouble(2**64+2)
18446744073709551616.0             # Note '6'; appears 2**64 not done in long double
>>> np.longdouble(int(2**64+2))
18446744073709551616.0             # can't force the use of a Python long
>>> n=int(2**64+2)
>>> np.longdouble(n)
18446744073709551616.0
>>> np.longdouble(18446744073709551618)
18446744073709551616.0             # It really does not want to do '8' at the end

しかし、これは機能します:

>>> np.longdouble(2**64)+2
18446744073709551618.0

質問: numpy には、値を long double に正しく変換する際の問題がありますか? 私が間違っていることはありますか?

4

2 に答える 2

10

直接変換できない型の間で型変換を実行しようとしています。スタックを見てください:

#0  0x00002aaaaab243a0 in PyLong_AsDouble ()
   from libpython2.7.so.1.0
#1  0x00002aaaaab2447a in ?? ()
   from libpython2.7.so.1.0
#2  0x00002aaaaaaf8357 in PyNumber_Float ()
   from libpython2.7.so.1.0
#3  0x00002aaaae71acdc in MyPyFloat_AsDouble (obj=0x2aaaaae93c00)
    at numpy/core/src/multiarray/arraytypes.c.src:40
#4  0x00002aaaae71adfc in LONGDOUBLE_setitem (op=0x2aaaaae93c00, 
    ov=0xc157b0 "", ap=0xbf6ca0)
    at numpy/core/src/multiarray/arraytypes.c.src:278
#5  0x00002aaaae705c82 in PyArray_FromAny (op=0x2aaaaae93c00, 
    newtype=0x2aaaae995960, min_depth=<value optimized out>, max_depth=0, 
    flags=0, context=<value optimized out>)
    at numpy/core/src/multiarray/ctors.c:1664
#6  0x00002aaaae7300ad in longdouble_arrtype_new (type=0x2aaaae9938a0, 
    args=<value optimized out>, __NPY_UNUSED_TAGGEDkwds=<value optimized out>)
    at numpy/core/src/multiarray/scalartypes.c.src:2545

ご覧のとおり、Python long(無制限の精度の整数)は(つまり、64 ビットの double)2**64 + 2に変換されており、精度が失われています。float次に float を使用して long double を初期化しますが、精度は既に失われています。

問題は、128 ビットの double がネイティブの Python 型でlongはないため、ネイティブな変換がなく、64 ビットの double にしか変換されないことです。longNumPy がこの状況を検出し、 C APIを使用して独自の変換を実行することはおそらく可能ですが、比較的メリットが少ないため、かなり複雑になる可能性があります (np.longdouble最初から算術演算を行うだけでかまいません)。

于 2013-08-30T16:31:16.283 に答える