Cで作成されたバイナリファイルからダブルを読み取るための最良の方法は何ですか?
質問
Cプログラムは連続したdoubleをバイナリファイルに吐き出します。それらをPythonで読みたい。 struct.unpack( 'd'、f.read(8))
編集: Cで次のコードを使用して、ランダムな倍精度数を記述しました
r = drand48();
fwrite((void*)&r, sizeof(double), 1, data);
エラーは修正されましたが、最初の値を読み取ることができません。すべての0.000 ..の数値については3.90798504668055と読みますが、残りは問題ありません。
解決
あなたは実際に数字を正しく読んでいると思いますが、ディスプレイに混乱が生じています。提供されたファイルから番号を読み取ると、「 3.907985046680551e-14
" -これはほとんどゼロではありませんが、ゼロではありません(展開された形式では0.000000000000039)。あなたのCコードは、Pythonよりも精度が低いだけでそれを印刷していると思われます。
[編集]ファイルをCで読み込んだところ、同じ結果が得られました(精度はわずかに劣りますが3.90799e-14)(printf("%g&quot ;, valを使用))。この値が正しくない場合は、読み取りではなく書き込み側で発生したと考えてください。
他のヒント
「動作しませんでした」について詳しく説明してください。コマンドはクラッシュしましたか?データが間違っていましたか?実際に何が起こったのですか?
コマンドがクラッシュした場合:
- コマンドのエラー出力を共有してください
データが単純に間違っている場合:
-
データを作成して読み取るシステムのエンディアンネスは同じですか?一方がビッグエンディアンで、もう一方がリトルエンディアンの場合、フォーマット文字列でエンディアン変換を指定する必要があります。
-
2台のコンピューターのエンディアンが同じ場合、データはどのようにファイルに書き込まれましたか?正確に?あなたは知っていますか?もしそうなら、ファイルに書き込まれた値は何で、間違った値は何でしたか?
まず、 pickle を試しましたか? まだ誰もPythonコードを表示していません... Pythonでバイナリを読み取るためのコードを次に示します。
import Numeric as N
import array
filename = "tmp.bin"
file = open(filename, mode='rb')
binvalues = array.array('f')
binvalues.read(file, num_lon * num_lat)
data = N.array(binvalues, typecode=N.Float)
file.close()
ここでfは単精度、4バイトの浮動小数点数を指定しました。エントリごとにデータのサイズを見つけて使用します。
非バイナリデータの場合、次のような簡単なことができます。
tmp=[]
for line in open("data.dat"):
tmp.append(float(line))
-
f.read(8)
は8バイト未満を返す場合があります -
データのアライメントやエンディアンが異なる場合があります:
>>> for c in '@=<>': ... print repr(struct.pack(c+'d', -1.05)) ... '\xcd\xcc\xcc\xcc\xcc\xcc\xf0\xbf' '\xcd\xcc\xcc\xcc\xcc\xcc\xf0\xbf' '\xcd\xcc\xcc\xcc\xcc\xcc\xf0\xbf' '\xbf\xf0\xcc\xcc\xcc\xcc\xcc\xcd' >>> struct.unpack('<d', '\xbf\xf0\xcc\xcc\xcc\xcc\xcc\xcd') (-6.0659880001157799e+066,) >>> struct.unpack('>d', '\xbf\xf0\xcc\xcc\xcc\xcc\xcc\xcd') (-1.05,)
最良の方法は、ASCIIテキストファイルを使用することです。
0.0
3.1416
3.90798504668055
移植性があり、あらゆる種類の浮動小数点実装である程度動作するという点。
double
のメモリアドレスから生のバイナリデータを読み取ることはまったく移植性がなく、いくつかの異なる実装では失敗する可能性があります。
もちろん、コンパクト化のためにバイナリ形式を使用することもできますが、その形式で記述したポータブルC関数はスニペットのようには見えません。
少なくとも、現在のマシンで使用される double
sのメモリ表現がPythonインタープリターで期待されるものと正確に一致することを確認する一連のifs / ifdefsでコードを囲む必要があります。
このようなコードを書くのは難しいでしょう。だからこそ、ASCIIテキストの簡単で、クリーンで、ポータブルで、人間が読めるソリューションを提案しています。
これは、「最高」の私の定義です。