浮點數 |
|
浮點數數字在 Lua 中成為唯一數字類型的主要問題在於大多數程式設計師不了解浮點數。浮點數數字比整數(定點數)還要複雜得多。大多數程式設計師對浮點數的心理模型是,運算結果有時會產生極輕微的誤差。因此,人們會因此而感到緊張。但此心理模型是錯誤的;將浮點數運算建模為「正確答案 + 雜訊」是錯誤的,特別是在處理最常見的浮點數類型 IEEE-754 時。
解決這個整體問題的方法是教育。 文件、網站、常見問答、wiki 等應該更多地強調雙精度浮點數的基本整數向後相容性。
在進一步探討之前,應注意到,儘管浮點數數字經常在 Lua 中用作數字類型,但 Lua 並不依賴浮點數,而且可以用任何一種數字類型進行編譯,例如單精度浮點數、整數,甚至是某些非常陌生的數字表示[*5]。當然,例如果您使用整數數字類型編譯 Lua,則除法等語義將發生重大變化,但這在嵌入式處理器上可能並不讓人感到意外。[*1] ARM、Coldfire 和各種類型的嵌入式 MIPS 沒有 FPU,但這些仍然很廣泛地使用。[*2]
以下是關於(IEEE 754)64 位元雙精度浮點數數字(「雙精度」)與 32 位元整數的一些重點
摘要:就準確度、範圍和「向後相容性」而言,64 位元精度的浮點數運算比 32 位元整數運算更好。不過,請參閱注意事項部分。
IEEE 754 定義基本的數學運算,+ - * (乘法)/(除法),以產生最接近準確數學答案的結果。特別是,如果答案正確可以表示為雙精度浮點數,那麼答案會是那個答案;否則,有兩個最接近準確答案的雙精度浮點數(一個高於,一個低於),其中一個會根據捨入模式選取。
對於涉及整數的運算,大多數運算都是準確的。如果我計算 2+5,則由於準確的數學答案為 7,它也是 IEEE 754 答案。
坦承來說,Intel 的 Pentium 設計名列第三(因為它的 FP 暫存器太少了)。但 Intel 正在迎頭趕上。
唯一剩下的效能考量是浮點數到整數轉換。不論你是否喜歡,記憶體載入指令都會使用一個地址和位元組位移(即兩個整數值)來運作。因此,如果 CPU 的浮點轉整數轉換效能在浮點運算中比整數運算差的話,使用浮點數代替整數進行任何效能儲存都將是徒勞的。有些說明指出,浮點轉整數轉換可能會對效能造成毀滅性的影響 [1]。(對於 gcc-3.4 和大約 2006 年的 AMD 處理器,問題已不復存在,但自行測試看看。從該連結編譯基準測試非常容易。)
對於這些嚴肅的現代桌上型 CPU 的使用者來說,唯一主要的潛在問題剩下記憶體頻寬和記憶體使用量。假設由於這些物件在 Lua 中的儲存格(聯合結構)大小,這些考量實際上無關緊要。
這方面的硬資料會很好,例如在各種(或一種)架構下配合單精密度和雙精密度浮點數配置的適當聯合的 sizeof()
。
-- 在 8 位元組結構對齊的世界中,它們實際上不會佔據更多空間,儘管如果物件結構因為 FP 數值的大小而超過 64 位元組,大小問題便會「該死地」顯而易見。FP 數值在 CPU 快取中也會佔用更多空間 -- 不僅暫存器會受到影響。 -- ChuckAdams
摘要:約在 2001 年,您平均入門級 10 美元的 CPU 晶片,有能力以 64 位元雙倍的速度和準確度(或更多)執行整數運算。這些 CPU 的使用者不應只因為在 lua 中使用雙倍浮點運算而付出任何成本,且有可能獲益。較小晶片的使用者很可能會被迫在 lua 中只使用整數運算。
-- 如下所述,使用最廣泛的嵌入式 CPU 之一,大多數 ARM 晶片沒有硬體浮點運算支援。這意味著每次在 int 和 float 之間的轉換,以及每次運算都是一個函式呼叫(通常為內嵌)。雙倍運算更糟。當您考慮到 NaN 和非正規化數字的檢查時,與整數相比,其負擔相當顯著(是的,我有實際測試)。--BenStJohn?
儘管 Lua 的數字類型可以建構為整數,但在使用前建議進行實際測試,因為(即使在僅限整數的處理器上),速度提升可能不如想像中那麼顯著,而且失去浮點運算可能會讓一些運算變得更複雜。另請注意,Lua 5.3 已內建明確的整數支援功能。
eLua http://www.eluaproject.net/ 是針對某些微控制器的一個 Lua 分支,它有一個選用的整數建置功能。然而,需要注意的是,標準 Lua 也很容易建置於像 ARM7TDMI 這類核心上,因為來源是標準 C。如果必要,可以套用整數變更。
printf
實作可能無法準確處理列印浮點數。相信與否,有些可能會錯誤地列印整數(浮點數)。這可能會表現為在 Lua 中錯誤地列印某些數字。QNX 就有這個問題 [2]。唯一明智的解決方式是向您的供應商抱怨並/或更換成可以正常運作的 printf
。
這些文章不依任何特定的相關順序所排列
-- MartinHollis(原作者)