指南為什麼浮點轉換器會失敗(以及十進制數學如何修復它)
為什麼浮點轉換器會失敗(以及十進制數學如何修復它)
了解為什麼二進制浮點會產生奇怪的轉換殘差,當這些錯誤很重要時,以及十進位或有理算術如何保持單位轉換器的可信度。
經典的 0.1 + 0.2 問題遇到單位
大多數 CPU 以二進位浮點數 (IEEE 754) 儲存非整數。在十進制中看起來很簡單的分數(0.1、0.001、2.54)通常無法用二進位精確表示。儲存的值是最接近的可表示的近似值,而近似值的算術會累積微小的殘差。
單位轉換重複乘除這些值。將英吋與毫米相互轉換,或將公升與立方公尺相互轉換,您可能會看到 2.9999999997,而不是 3。物理轉換係數是準確的;計算機表示則不然。
對於許多顯示器來說,四捨五入後差異是不可見的。對於與財務相關的劑量、數控刀具路徑、合法土地面積或期望完全相等的自動測試斷言,這些殘差會成為真正的錯誤。
哪些換算係數在紙上是準確的
國際吋正好是25.4毫米。國際英尺正好是 0.3048 m。一公升正好是 0.001 立方公尺。在通常的實驗室意義上,一立方厘米正好是 1 毫升(1 立方厘米 = 10⁻⁶ 立方米)。這些是定義,而不是測量。
如果軟體將 25.4 儲存為二進位浮點數,則在任何轉換運行之前可能已經出現輕微錯誤。乘以另一個不精確的因子會加劇誤差。即使演算法在概念上是正確的,斷言嚴格相等的往返測試也會失敗。
溫度添加偏移量:攝氏度 ↔ 開爾文使用 273.15。此常數也是二進制浮點數的近似十進制值。仿射轉換特別敏感,因為添加不精確的偏移量會改變每個結果。
實踐中出現浮點錯誤的地方
UI 轉換器通常會透過四捨五入到固定的小數位數來隱藏問題。使用者看到乾淨的結果而不會注意到內部噪音。當另一個系統使用原始浮點數時就會出現問題:CAD 核心、CSV 匯出或比較全精度字串的單元測試。
連鎖轉換會加劇麻煩。每一步都帶有二進制浮點數的英里→碼→英尺→英寸→毫米→米比具有高精度係數的單英里→米轉換要差。每跳都會重新捨入中間值。
數量的平方和立方會使錯誤變得更嚴重。面積和體積會乘以長度比例,因此當您展開 (1+ε)ⁿ 時,長度上的微小相對誤差相對於面積或體積而言會變得大兩倍或三倍。
小數、有理數和定點替代方案
小數庫(例如,decimal.js、Big.js 或語言本機小數)以 10 為基數儲存數字。精確的小數因數(例如 0.3048 和 0.001)在所選精度範圍內保持精確。關心正確性的單位轉換器通常透過十進制基本單位進行轉換。
有理算術將因子儲存為整數的分數。如果 1 英吋 = 127/5000 公尺(因為 25.4 毫米 = 127/5000 公尺),乘法可以完全抵消。有理數對於純尺度轉換來說是理想的;偏移仍然需要仔細處理溫度。
定點數學將所有內容縮放到最小刻度的整數計數(奈米、微升或千分之一英吋)。整數運算在溢位之前都是精確的。它適用於具有明確測量量的領域。
值得信賴的轉換器的實用規則
將精確的法律因子儲存為小數或有理數,而不是倉促鍵入的二進制浮點數。以盡可能少的步驟轉換輸入 → 基礎 → 輸出。僅在針對人類進行格式化時進行舍入,並記錄舍入模式。
切勿在二進制浮點數上測試嚴格相等的轉換器。在絕對或相對容差範圍內進行比較,或以規定的精度比較十進位字串形式。首選使用已知精確對的黃金測試,例如 1 英吋 = 25.4 毫米。
如果您建立計算器 UI,請顯示足夠的精度以供使用,但不要顯示過多的數字,以免浮動雜訊看起來像訊號。透過浮點數轉換後顯示十二位小數的長度工具正在宣傳其表示錯誤。
當二進制浮點仍然沒問題時
粗略比較、遊戲、數據視覺化和許多科學模擬都可以容忍浮動誤差,因為模型的不確定性使表示誤差相形見絀。關鍵是了解你的耐受力。如果一毫米很重要,那麼浮標就需要紀律或更換。
硬體加速和 GPU 管道通常會強制浮動。在這些情況下,請在 CPU 或伺服器上保留十進位的權威轉換,並將 GPU 浮點視為顯示或中間近似值。
好的工程是將數字表示與您將用數字做出的決定相匹配。製造、醫學和法定計量的單位轉換需要小數或理性數學;天氣小部件不會轉換城市溫度。如有疑問,請選擇更嚴格的表示法 - 小數的性能成本通常小於靜默往返錯誤的成本。
相關換算器
常見問題
為什麼來回轉換會改變我的號碼?
二進制浮點數不能準確地表示許多小數因數。每次乘法或除法都會增加微小的捨入誤差。即使轉換因子在概念上是準確的,通過浮點的往返轉換通常也無法恢復原始位元。
雙精度足以進行單位轉換嗎?
雙精度 (float64) 足以滿足顯示舍入後的許多日常轉換,但當您需要位元穩定的往返、法定計量或嚴格的自動化測試時,它並不能取代精確的小數因數。對於權威轉換器,喜歡小數或有理數。
我應該如何比較測試中的轉換器結果?
以聲明的精確度進行比較,使用十進位字串相等,或斷言絕對和相對容差。避免在幾個算術步驟之後期望精確的二進制相等。