10

Python 2.7.5 で次のコードを実行します。Windows の場合:

import os, shutil, stat, time

with open('test.txt', 'w') as f: pass # create an arbitrary file
shutil.copy('test.txt', 'test2.txt') # copy it
shutil.copystat('test.txt', 'test2.txt') # copy its stats, too

t1 = os.lstat('test.txt').st_mtime # get the time of last modification for both files
t2 = os.lstat('test2.txt').st_mtime

print t1 # prints something like: 1371123658.54
print t2 # prints the same string, as expected: 1371123658.54
print t1 == t2 # prints False! Why?!

両方のタイムスタンプ (=floats) が等しい (文字列表現が示唆するように) と予想しているのに、なぜ がt1 == t2と評価されるのFalseですか?

os.lstatまた、 2 つの異なるファイルから取得したタイムスタンプを比較せずに、より少ないコードでこの動作を再現することもできませんでした。ここで些細なことを見逃しているような気がします...


編集:さらにテストした結果、たまに印刷されることがわかりTrueましたが、10回の実行ごとに1回以上は印刷されません。


編集 2: larsmans の提案によると:

print ("%.7f" % t1) # prints e.g. 1371126279.1365688
print ("%.7f" % t2) # prints e.g. 1371126279.1365681

これにより、次の 2 つの新しい疑問が生じます。

  1. を呼び出した後、タイムスタンプが等しくないのはなぜshutil.copystatですか?
  2. printデフォルトでフロートを丸めますか?!
4

3 に答える 3

7

問題は、通話中の異なるフォーマット間の変換にありcopystatます。これは、Windows がファイル時刻を固定小数点 10 進数形式で格納するのに対し、Python は浮動小数点バイナリ形式で格納するためです。そのため、2 つの形式間で変換が行われるたびに、精度がいくらか失われます。copystat通話中:

  1. への呼び出しはos.stat、Windows 形式を Python の浮動小数点形式に変換します。一部の精度が失われます。
  2. os.utimeファイル時刻を更新するために呼び出されます。これにより、Windows 形式に変換されます。再びいくらかの精度が失われ、ファイル時間は必ずしも最初のファイルと同じではありません。

自分自身を呼び出すos.lstatと、3 番目の不正確な変換が実行されます。これらの変換により、ファイル時間は正確には同じではありません。

ドキュメントにos.utimeは、次のことが記載されています。

ここで設定した正確な時刻は、オペレーティング システムがアクセスおよび変更時刻を記録する解像度によっては、後続の stat() 呼び出しで返されない場合があることに注意してください。


print2番目の質問について(両方に同じ値が表示されるのはなぜですか):浮動小数点値をstr(f)またはで文字列に変換するprint fと、値が丸められます。異なる浮動小数点値に対して一意であることが保証された値を取得するには、print repr(f)代わりに を使用してください。

于 2013-06-13T12:53:34.937 に答える
0
from decimal import *
print Decimal(t1)
print Decimal(t2)

t1 と t2 に round() を使用する

于 2013-06-13T12:47:07.273 に答える
-1

浮動小数点で時差を出力してみてください:print float.hex( t1 - t2)

結果:

0x1.0000000000000p-22
0x1.8000000000000p-21
0x0.0p+0
0x1.0000000000000p-20

私の2セントの推測:出力の変動は、浮動小数点表現のバイアスと丸め誤差に起因します。とにかく、2 つの float を比較するときは、常にイプシロン値を使用する必要があります。

編集: このPython バグを確認してください。

これはシステムの制限です。基盤となるファイル システムは、ファイル スタンプのナノ秒単位の解像度をサポートし、stat(2) もそれらのレポートをサポートします。ただし、utimes(2) は、設定時にマイクロ秒の解像度しかサポートしません。

2 つの float を比較するときは、せいぜいマイクロ秒の解像度を使用する必要があります。

于 2013-06-13T12:43:43.997 に答える