5

以下をApp Engine Shellに入れると、 が得られ'50.49'ます。この結果は、2.5 ランタイムと 2.7 ランタイムの両方で一貫しています。

 >> a = '%0.2f' % (round(float(u'50.485'), 2),)
 >> a
'50.49'

ただし、python 2.7.1 を実行しているローカルの MacBook Pro に同じものを入れると、'50.48'.

 >> a = '%0.2f' % (round(float(u'50.485'), 2),)
 >> a
'50.48'

この違いはなぜですか? また、ローカル マシンと App Engine のサーバーの間で一貫性を保つにはどうすればよいですか?

4

3 に答える 3

4

どうやら、Google App Engine は "float" C タイプ (IEEE 754 単精度) を使用するのに対し、ローカル Python は代わりに "double" (IEEE 754 倍精度) を使用します。

CPython には「double」の代わりに「float」を使用するための構成スイッチがあると思われますが、見つかりませんでした。

于 2013-01-28T12:51:03.950 に答える
2

面白いことに、この正確なトピックは公式の Python チュートリアルでカバーされています。

浮動小数点演算: 問題と制限
http://docs.python.org/2/tutorial/floatingpoint.html

このことから、他の驚きが続きます。たとえば、値 2.675 を小数点以下 2 桁に丸めようとすると、次のようになります。

>>>
>>> round(2.675, 2)
2.67

組み込みの round() 関数のドキュメントには、最も近い値に丸め、タイをゼロから遠ざけるように丸めると書かれています。小数の 2.675 は 2.67 と 2.68 の丁度中間であるため、ここでの結果は (バイナリ近似で) 2.68 になると予想されるかもしれません。そうではありません。10 進文字列 2.675 が 2 進浮動小数点数に変換されると、正確な値が 2 進近似に再び置き換えられるからです。

2.67499999999999982236431605997495353221893310546875

この近似値は 2.68 よりも 2.67 にわずかに近いため、切り捨てられます。

小数の中間ケースがどのように丸められるかを気にする状況にある場合は、 decimal モジュールの使用を検討する必要があります。ちなみに、decimal モジュールは、特定の Python float に格納されている正確な値を「見る」良い方法も提供します。

>>>
>>> from decimal import Decimal
>>> Decimal(2.675)
Decimal('2.67499999999999982236431605997495353221893310546875')

公式の Python チュートリアル ( http://www.lahey.com/float.htm ) からリンクされている記事の 1 つは、FORTRAN を使用しているにもかかわらず、IEEE 754 の実際の意味を正しく説明しています。

異なるコンピューターは、異なる数のビットを使用して浮動小数点数を格納します。数値の格納に同じ IEEE 形式が使用されている場合でも、中間レジスタのサイズが原因で計算に違いが生じることがあります。移植性を高め、結果の一貫性を確保するために、FORTRAN で実数の正確な等価性を比較しないことをお勧めします。

したがって、これを本当に気にする場合は、組み込みの decimal モジュール (または、パフォーマンスが問題になる場合はhttp://pypi.python.org/pypi/cdecimal/2.3から入手できる cdecimal モジュール) を必ず使用してください。

于 2013-01-28T12:41:15.843 に答える
0

他の答えは正しいので、関数の動作については何も言いませんが、例で示したように文字列形式 ( ) を使用しているため、round一貫した結果が必要な場合は をスキップできます。round'%0.2f'

>> a = '%0.2f' % (float(u'50.485'))
>> a
'50.48'
于 2013-01-28T13:08:11.157 に答える