2017-09-21 10 views
1

私は非常に大きな整数でnumpy.divmodを使用しようとしていました。私は奇妙な動作に気付きました。周り2**63 ~ 1e19(3.5+ Pythonでintの通常のメモリ表現の限界であるべき)で、この問題が発生した:どういうわけかPython numpy.divmodと整数表現

from numpy import divmod 

test = 10**6 
for i in range(15,25): 
    x = 10**i 
    print(i, divmod(x, test)) 

15 (1000000000, 0) 
16 (10000000000, 0) 
17 (100000000000, 0) 
18 (1000000000000, 0) 
19 (10000000000000.0, 0.0) 
20 ((100000000000000, 0), None) 
21 ((1000000000000000, 0), None) 
22 ((10000000000000000, 0), None) 
23 ((100000000000000000, 0), None) 
24 ((1000000000000000000, 0), None) 

、商と余りは2**63まで正常に動作し、その後、別の何かがあります。

私の推測では、int表現は(LongのリトルエンディアンSeqとして、すなわち、ScalaではBigIntように)「ベクトル化」であるということです。しかし、私は、divmod(array, test)という結果として、商の配列と剰余の配列のペアを期待しています。

私はこの機能について手掛かりがありません。組み込みdivmodでは発生しません(すべて正常に動作します)

これはどうしてですか?それはintの内部表現で関係がありますか?

詳細:numpyのバージョン1.13.1、のpython 3.6

+0

私は[バグレポート](https://github.com/numpy/numpy/issues)を提出することをお勧めします。あなたの質問が何であるかはわかりません(たぶんバグのある行動を見せてくれることは別として)。 – MSeifert

+0

もっと正確な質問を追加しました。バグかもしれないが、合理的な(そして一貫した)説明があるのだろうか。 – pazqo

答えて

2

問題はnp.divmodは、配列に引数を変換することで、何が起こるかは本当に簡単です:

>>> np.array(10**19) 
array(10000000000000000000, dtype=uint64) 
>>> np.array(10**20) 
array(100000000000000000000, dtype=object) 

あなたがobject配列を取得します10**ii > 19があり、それ以外の場合は「実際のNumPy配列」になります。

そして、object配列はnp.divmodで奇妙な動作のように確かに、それはそう:

>>> np.divmod(np.array(10**5, dtype=object), 10) # smaller value but object array 
((10000, 0), None) 

私は通常ののPython内蔵divmodこの場合には推測最初の返された要素を計算し、残りのすべての項目が満たされていますNoneで、Pythons関数に委譲しています。

objectアレイは、多くの場合、ネイティブdtypeアレイとは異なる動作をすることに注意してください。それらはずっと遅く、しばしばPython関数に委譲します(これはしばしば異なる結果の理由です)。

+0

これはそれだ!私は "オブジェクト"にキャストを期待していなかった。彼らは実際には遅いですが、実際にはdivmodはnp.divmodよりも10倍高速です(オブジェクトのキャスティングによってオーバーヘッドが増加すると思います)。ありがとうございました! – pazqo