2017-03-07 5 views
0

Python2.7でnumpy配列との間でデータ型を間違って割り当てたり変換したりしているので、私が問題を引き起こしているのか疑問に思っています。NumPy:dtype float64でnp.arrayにint64値を格納して後で整数に変換するのは安全ですか?

私がやっていることは、numpy.float64型からnumpy.zeros()配列にhdf5の64ビット整数値を読み込むことです!次に、これらの値を別のhdf5に書き込んで、64ビットの符号なし整数を割り当てます。

12028545243 
12004994169 

質問1:実際にID番号(彼らが原因のデータ型変換に変化しないことが重要である)は、いくつかの元の値の

2つの例示をウィルにその符号なし整数2番目のhdf5ファイルは元のものと同じですか?

小さなサブサンプルでこれを確認しましたが、それがすべての場合に真であるかどうかは制御できません(何百万もあります)!

質問2:私は、データ型=のfloat64とnumpyのアレイに、元のファイルから64ビットの値を読み込み、その後のようなものやっている場合は、次のことが正確になります

value=int(value) 
value.astype(int64) 

を元の価値か、それとも変容のために変わるのか?

質問3: Pythonは(a)、(b)、(c)、(d)と仮定して値を解釈しますか?科学的表記「e + 10」のように、値の書式設定に問題がありますか?それとも、Pythonはそれらを同じ値として認識しますか?

1.20285452e+10 == 12028545243.0 == 12028545243 == 12028545243 
1.20049942e+10 == 12004994169.0 == 12004994169 == 12004994169 
(a)    (b)    (c)   (d) 

配列名前付きデータの1列印刷(a)に記載されている値:

print data[:,0] <type 'numpy.ndarray'> 

(b)のデータ変換を行った後

print data[0,0] <type 'numpy.float64'> 

(C)における単一の要素を印刷します

print int(data[0,0]) <type int> 

(d) (a)しかし、astype()を使って変換する!

print data[:,0].astype(numpy.int64) <type 'numpy.ndarray'> 
なぜ私はint64型をnumpy配列に割り当てて安全でないのか尋ねることがありますか?はい、私はそれを行いますが、既に間違って格納されているデータがあり、私はまだこのデータを信頼できるかどうかを知る必要があります...

私は使用しています:Python2.7、Pythonbrew、Ubuntu 14.04 LTS 64ビットon Lenovo T410

答えて

0

一般に、64ビット整数を64ビット浮動小数点数に格納することはできません。あなたは簡単に見ることにより、例えばそれを見ることができます:

import numpy as np 
print(np.int64(2**63-1)) 
print(np.int64(np.float64(2**63-1)) 

最初の第二は、整数オーバーフロー(-9223372036854775808)になり丸め誤差を持っているあなたに正しい結果(9223372036854775807)を得ますが。

これを理解するには、これらの数値の保存方法を確認する必要があります。整数は基本的に絶対値を2進数で格納するだけですが(数値の符号に1ビット加えて)、これは浮動小数点数では保持されません。

浮動小数点数は3つの部分で数値を格納します。 1つは符号ビットであり、次は重要/仮数であり、最後は指数である。この数は、符号時間の仮数2×指数として与えられる。これらの3つは利用可能なビットを共有する必要があります(ケース64)。 にはnp.float64のように52ビットが有効であり、11ビットが指数に使用されています。したがって、最大52ビットの整数の場合に限り、np.float64に変換して戻すと正しい結果が得られます。

第1と第2の質問に答えてください:いいえ、あなたのデータセットに2**52-1より大きい数字があれば、数字が同じであることを確認することはできません。

第3の質問:書式設定は値を印刷するときにのみ行われます。数値を内部的に比較する場合、数字には全く同じ値を持つ限り、それらの値はすべて等しいと見なされるような書式はありません。

Btw浮動小数点演算の詳細については、David Goldbergの論文"What every computer scientist should know about floating-point arithmetic"をご覧ください。

+0

お手数をおかけしていただきありがとうございます。 – firefly2517

0

Numpyがint64の値をfloat64に変換してからintに戻すか、またはintデータをfloat64用に予約されたメモリに格納するかによって異なります。私は最初のオプションが真であると仮定します。 float64 internaを調べなくても(魔法は何とかやるべきことです)。浮動小数点64には2**64の異なる整数があり、それ自体が2**64の異なるコードしかなく、0.1などのいくつかを必要とするならば、float64は一意の表現を持つことはできません。 float64は、53ビット長の正規化された仮数を(最上位ビットが暗黙1)を格納するために52ビットを使用するので、あなたの整数がよりそれら52ビットのような最初のものの後の非ゼロ・ビットを有する場合:(

 5764607523034234887 
    = 0x5000000000000007 
    = 0b0101000000000000000000000000000000000000000000000000000000000111 

魔法使いは完全に細かい64ビット整数です)

最後の0b111部分は、仮数部に数を適合させるために二重に変換した後に丸めて失われます。この情報は永遠に失われます。これは通常、かなり大きな数字なので、あなたのIDのいくつかで起こる可能性があります。 代わりに配列をint64に調整してみてください。

+0

ありがとうございました! ID番号がそれほど大きくなく、私は署名なしでしか使用していないので、私はおそらく迅速な解決策を見つけることができると期待していました。しかし、それは私が最初から始める必要があるようです... – firefly2517

関連する問題