2017-08-16 73 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:

1)我使用Python 2.7

2)我最終使用它的功能。這給特殊情況帶來了意想不到的結果。我無法控制輸入數據質量及其數據精度,因爲它是通過讀取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很陌生,但我猜浮點數會有問題。導入小數將使我精確得多。只要'輸入小數' – 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),我們再次從整數移動到浮點,但是具有正確的期望值(從過去的一週開始,在生產中運行至今沒有意外)。理論上你知道它只有2個小數位(整數除以20),所以如果需要的話,你可以在程序的其餘部分通過在打印時刪除其餘部分來處理它。

+1

這不是一個好的解決方案。它可能對你測試過的那些情況「起作用」,但你最終會發現其他的例子,其中的事情圍繞着「錯誤」的方式。 –

+0

@Mark更新了答案。不幸的是,像'Decimal'這樣的其他方法不適用於我,因爲數據輸入已經處於浮動狀態,並且精度已經丟失。令人驚訝的是,關於這個問題有很多文檔,但大部分都是關於解釋這個問題的。很少有解決方案。 所以擴大邏輯是我可以用來處理這種情況的最佳選擇(我可能是錯的)。 如果您有任何其他解決方案,請轉達。 – Wacao