當前位置: 華文問答 > 數碼

為什麽在專案中要盡量避免使用浮點數,不使用浮點數,那該如何計算浮點數?

2017-10-02數碼

「在專案中要盡量避免使用浮點數」本來就是個偽命題,很大程度上是以訛傳訛得來的,比方說上面回答中那個猴子的故事就很形象。

這個以訛傳訛的本體來源於工程需求,往往是要讓人盡量用整數,卻忽略了整數跟浮點同樣都是有限精度。

如果你需要無限精度,那麽只有自訂類別能滿足。整數vs浮點並沒有太大的優勢。

實際上,浮點的誤差來自十進制小數跟二進制小數之間的轉換。如果這個轉換對你具體的套用來說不是必須的,那麽你就完全可以用浮點。

因而,不應該使用浮點數的常用場合只有一個,那就是:當你需要讓一個變量精確的對應到現實中某個十進制小數時,不應當使用浮點小數來保存這個變量。當十進制小數與二進制浮點小數的轉換不可避免,你又必須要求精度時,不應當使用浮點。

比方說 1.1 元錢,因為這個變量必須精確的等於十進制的 1.1,而變量本身是二進制,此時進制轉換是必須的,所以你用浮點小數保存是錯誤的,你可以考慮用精確到分的 110 來表示這個數碼,避免了小數。類似的,如果是小算盤的話,如果使用者是用十進制的格式輸入,那麽直接轉換成二進制用電腦進行運算,最後再轉換成十進制顯示,這就不可避免的會有誤差。

如果沒有進制轉換的需求,那麽用浮點沒有任何問題, 甚至不會有精確性方面的問題

那麽舉一些可以用浮點數例子:

1,如果你有一個只需要在計算過程中出現的變量,它的輸入並不來源於十進制小數,也不需要被轉換成十進制保存,那麽它完全可以用浮點,最典型的就是遊戲,你需要使用一個很復雜的增傷減傷公式來計算出實際的傷害,而這個傷害直接的被作用到了目標,在整個過程中,所有的操作都使用二進制進行,不存在二進制十進制轉換,因此就不會產生誤差,此時用浮點根本沒有問題。——當然在遊戲中,即便其中的變量最終需要以十進制顯示,你仍然可以用浮點,因為十進制顯示雖然有誤差,但可以四舍五入顯示,不需要絕對精確。

2,如果你的浮點僅僅用來儲存精度內的整數,那麽使用它也不會存在問題。例如 64 位浮點可以用來精確儲存 2^47 以內的整數,不會存在任何誤差。換句話說就是 64 位浮點可以無失真的放進一個 32 位的 int,不存在任何誤差,在 32 位整數不夠用,系統又不支持 64 位整數時,它也可以被當作 47 位的整數類別使用。(47這個數碼有爭議,有說48,52,53等等的,但不影響具體結論,都大於32,裝32位元整數依然可以完全精確表示。)

同理,32 位的浮點則可以精確的放進一個 2^23 以內的整數,不存在任何誤差。 32 位浮點變量保存一個 16 位的 short 類別整數不產生任何誤差,它也可以被當作一個精度在 23 bit 的整數類別。

3,可能存在的其他例子,歡迎補充。

--

補充,其實有一個不應該使用浮點的不常用場合,就是目標cpu沒有浮點處理器,此時的浮點使用整數模擬計算出,效率極低。鑒於現代的絕大多數大多數CPU都配備了浮點處理器,浮點運算的效能跟整數是相當的。如果使用現代的cpu,需要避免浮點的情況發生概率很小。但在一二十年前,有很多cpu(尤其是嵌入式cpu)還沒有配備浮點處理器,此時確實應該盡量避免,甚至完全避免用浮點。