2017-08-16 10 views
-2

最も近い0.05に丸めるには、0.05で除算してから0.05を掛けます。他の同様の質問に記載されています。最も近い0.05に丸めている間違ったケース - 特別なケース

In [119]: (127.651//0.05)*0.05 
Out[119]: 127.65 

In [120]: (127.6501//0.05)*0.05 
Out[120]: 127.65 

In [121]: (127.65000001//0.05)*0.05 
Out[121]: 127.65 

In [122]: (127.65000000001//0.05)*0.05 
Out[122]: 127.65 

In [123]: (127.6500000000001//0.05)*0.05 
Out[123]: 127.65 

ここまで期待通りに行っています。 しかし、この特殊なケースのために:

In [124]: (127.650000000000000001//0.05)*0.05 
Out[124]: 127.60000000000001 

私はここに127.65を期待しているだろう。

分割前に四捨五入を試みましたが、もう一度奇妙です。 予期せぬ結果(127.65が予想されます)だけでなく、小数点以下2桁を超える結果が得られます。

In [125]: (round(127.650000000000000001,5)//0.05)*0.05 
Out[125]: 127.60000000000001 

私はちょうど内側のラウンドを実行する場合は、O/pは127.65 ...

In [126]: round(127.650000000000000001,5) 
Out[126]: 127.65 

である。しかし除算を追加し、ロジックを掛け..に結果が予想外になります。

In [125]: (round(127.650000000000000001,5)//0.05)*0.05 
Out[125]: 127.60000000000001 

データ型に問題はありますか?またはpythonの内部精度の制限?

どのように私はエレガントな方法でそれを克服するのですか?

PS:私のpython 2.7

2を使用しています

1))私は最終的機能でそれを使用しています。この特別な場合に予期しない結果をもたらすものです。私は入力データの品質とそのデータ精度を制御することはできません。それは、CSVファイルをデータフレームに読み込むことから来ています。

def RP(price):# Round down to the nearest price quotable ...i.e. multiple of 0.05 
     return(round(price//0.05*0.05,2)) 
+1

さらに古典的な[浮動小数点演算は壊れていますか?](https://stackoverflow.com/q/588004/3001761)。正確な表現が必要な場合は、['Decimal'](https://docs.python.org/3/library/decimal.html)の使用を検討してください。 – jonrsharpe

+0

私はpyにはとても新しいですが、浮動小数点数には問題があると思います。 10進数をインポートすると、それは私が推測するより正確になります。ちょうど 'import decimal' – ihpar

+0

ヒント:' 127.6500000000000056 == 127.65'とは何ですか?答えはあなたを驚かせるか? –

答えて

0

最後に、is-floating-point-math-brokenに記載されているスケールアップロジックが私に役立ちました。

In [200]: (int(127.65*100)//5*5)/100.0 
Out[200]: 127.65 

In [201]: 

In [201]: (int(127.65000000000000001*100)//5*5)/100.0 
Out[201]: 127.65 

か:

In [286]: int(127.65*20)/20.0 
Out[286]: 127.65 

In [287]: int(127.6500000000000000000000001*20)/20.0 
Out[287]: 127.65 

UPDATE:私の目的のために

、(最も近い0.05に丸めることは価格の引用を得るために)、これまでに以下が最も最も近いソリューションです検索とチェックの結果、複数の値や繰り返しを見つけた後に見つけることができます。

def RP(price):# Round to the nearest price quotable ...i.e. multiple of 0.05 
     return(round(price*20.0,0)/20.0) 

def RP_down(price):# Round_Down to the price quotable ...i.e. multiple of 0.05 
     return(int(price*20.0)/20.0) 

def RP_up(price):# Round_UP to the price quotable ...i.e. multiple of 0.05 
     return(0.05 + int(price*20.0)/20.0) 

なぜ機能するのですか?以下の説明は次のとおりです。

20.0に続けてround()またはint()を掛けて、ドメインを浮動小数点から整数に変更します。

したがって、予期しない結果につながる精度の問題を排除します。

注:最後のステップでは(20で割ります。0)、再び整数から浮動小数点へと移動しますが、正しい期待値を使用します(これまでの生産から1週間後に驚きはありません)。理論的には小数点以下2桁しか持たないことを確かに知っているので、必要に応じて残りの部分を切り取って印刷しながら残りの部分を処理することができます。

+1

これは良い解決策ではありません。あなたがテストしたケースのカップルのためにあなたのために「うまくいく」かもしれませんが、最終的には「間違った」方法のどこかで他の例が見つかります。 –

+0

@Mark答えを更新しました。残念ながら、データ入力がすでに浮動小数点であり、精度が既に失われているため、 'Decimal'カントを使用するような他の方法は私のために働きます。意外にも、この問題に関する多くの文書がありますが、その大部分は問題の説明です。ソリューションにはごくわずかです。 このケースを処理するために使用した可能性のあるスケーリングアップロジックが最適なオプション(私は間違っている可能性があります)でした。 他に解決策がある場合は、お伝えください。 – Wacao

関連する問題