2016-11-09 72 views
0

我正在處理一些就地顯示的格式化用戶存儲的浮點數的就地代碼。Python格式字符串和浮點表示法

當前實現做到這一點:

"{0:.24f}".format(some_floating_point).rstrip('0') 

這是有道理的和工作得很好大部分。但是當遇到像0.0003這樣的價值時,情況就不一樣了。

>>> "{0:.24f}".format(0.0003).rstrip('0') 
'0.000299999999999999973719' 

一些進一步的調查表明,Python似乎根據請求的位數改變了底層表示法?

>>> "{0:.15f}".format(0.0003) 
'0.000300000000000' 
>>> "{0:.20f}".format(0.0003) 
'0.00029999999999999997' 

我的假設是單精度vs雙精度。

用戶輸入這些值作爲double值存儲在數據庫中,並且稍後再次呈現表單時,相同的值將在字段中預先填充。因此我需要這些表示的1:1映射。

因此,我的問題是:什麼是處理這種行爲的優雅,更重要的安全方法?迄今爲止我所做的最大努力都涉及到log10,並且不太理想地把它放在很好的位置。

編輯:由於Prune指出價值並沒有真正改變,而是由格式完成的舍入將繼續導致一組9個變爲0(德)。這種行爲是有道理的,但解決方案仍在逃避我。

+0

沒有一個優雅的解決這一點,它在基地2座10我可以提供答案之間的差別所固有的,但它也需要日誌10 - 你需要限制的位數格式要比存儲在double中的有效數字少一個。 –

回答

1

您正在接收存儲的號碼。 0.0003不能完全存儲爲二進制分數。舉例說明:

>>> 0.00029999999999999997 == 0.0003 
True 

打印格式將四捨五入最低位的數字。雙精度只會將問題推向右側。要將問題完全「解決」到base-10眼睛,您需要切換到十進制算術,或者可以爲足夠接近較簡單值的數字構建您自己的字符串處理程序(小數部分爲9或0的可疑字符串)。


這是您的一個函數的開始。我用0.0004進行了測試,它的存儲量超過了0.0004; 9的情況留作練習:-)。

def str_round(x): 
    size = 6 
    nines = '9'*size 
    zeros = '0'*size 

    str = "{0:.24f}".format(x).rstrip('0') 
    str_len = len(str) 
    print str, str_len 

    if nines in str: 
     # replace leading digit with one more 
     pos = str.index(nines) 
     # ADD CODE HERE 
     # Turn the leading portion into an integer; 
     # increment and convert back to zero-leading string. 
     # Fill out the rest with zeros. 

    elif zeros in str: 
     # Change all trailing digits to 0 
     pos = str.index(zeros) 
     str = str[:pos] + '0'*(str_len - pos) 

    return str 

print str_round(0.0004) 
+0

啊哈,我不知道如何,例如29999可以達到30000.因此,當要求格式化一個不是9的數字時,它會「打破」。出於某種原因,我認爲這是在做更復雜的事情。但仍然沒有提供很多解決方案。 – Zigsaz