Rust智能合約內數值精算技巧:避免浮點數陷阱

Rust智能合約養成日記(7)數值精算

1. 浮點數運算的精度問題

不同於常見的智能合約編程語言Solidity,Rust語言原生支持浮點數運算。然而,浮點數運算存在着無法避免的計算精度問題。因此,在編寫智能合約時,並不推薦使用浮點數運算,尤其是在處理涉及到重要經濟或金融決策的比率或利率時。

目前主流計算機語言表示浮點數大多遵循了IEEE 754標準,Rust語言也不例外。雙精度浮點類型f64在計算機內部以二進制數據形式保存。

浮點數採用了底數爲2的科學計數法來表達。例如可以用有限位數的二進制數0.1101來表示小數0.8125。然而對於0.7這樣的小數來說,其轉化爲浮點數的過程中將出現無限循環的二進制表示,無法用有限位長的浮點數來準確表示,並存在"舍入"現象。

假設需要分發0.7個代幣給十位用戶,每位用戶分得的代幣數量將計算保存於result_0變量中。執行相關測試用例後,我們可以發現amount的值並非準確地表示了0.7,而是一個極爲近似的值0.69999999999999995559。進一步的,對於amount/divisor的單一除法運算,其運算結果也將變爲不精確的0.06999999999999999,並非預期的0.07。由此可見浮點數運算的不確定性。

對此,我們需要考慮在智能合約中使用其它類型的數值表示方法,如定點數。在實際的智能合約編寫中,通常會使用一個具有固定分母的分數來表示某一數值,例如分數x/N,其中N是常數,x可以變化。

在某些公鏈中,N常見的取值爲10^24,即10^24個最小單位等價於1個主要代幣單位。基於此,我們可以將浮點數運算改爲整數運算,以獲得更精確的計算結果。

2. Rust整數計算精度的問題

使用整數運算可以解決某些場景中浮點數運算精度丟失的問題。但這並不意味着整數計算的結果完全準確可靠。影響整數計算精度的部分原因包括:

2.1 運算順序

同一算數優先級的乘法與除法,其前後順序的變化可能直接影響到計算結果,導致整數計算精度的問題。對於整數除法而言,小於除數的精度會被舍棄。因此在某些計算過程中,如果先進行除法運算可能會導致精度丟失。

2.2 過小的數量級

當涉及的數值過小時,整數運算也可能出現精度問題。例如,在某些情況下,直接進行整數運算和引入更大數量級後再運算可能會得到不同的結果。

3. 如何編寫數值精算的Rust智能合約

爲了保證智能合約中的計算精度,可以採取以下防護手段:

3.1 調整運算的操作順序

盡量讓整數乘法優先於整數的除法進行。

3.2 增加整數的數量級

使用更大的數量級來表示數值,創造更大的分子參與運算,以提高精度。

3.3 積累運算精度的損失

對於無法避免的整數計算精度問題,可以考慮記錄累計的運算精度損失。在後續運算中將這些損失納入考慮,以實現更公平的結果分配。

3.4 使用Rust Crate庫rust-decimal

該庫適用於需要高精度計算且無舍入誤差的小數金融計算場景。

3.5 考慮舍入機制

在設計智能合約時,舍入問題通常遵循"對己有利,不利他人"的原則。根據具體情況選擇向下取整、向上取整或其他適當的舍入方式。

通過採取這些措施,可以在Rust智能合約中實現更加精確的數值計算,避免因精度問題而導致的錯誤或不公平結果。

查看原文
此頁面可能包含第三方內容,僅供參考(非陳述或保證),不應被視為 Gate 認可其觀點表述,也不得被視為財務或專業建議。詳見聲明
  • 讚賞
  • 8
  • 轉發
  • 分享
留言
0/400
资深老韭当家vip
· 07-19 12:17
精度确实坑人
回復0
跑路预言家vip
· 07-18 09:14
精度把控要到位
回復0
Gas_Optimizervip
· 07-16 19:00
精度即是生命
回復0
测试网学者vip
· 07-16 18:56
去整数算更靠谱
回復0
gas费烧烤摊vip
· 07-16 18:46
比率乘以10000
回復0
GweiWatchervip
· 07-16 18:46
精度坑太多了
回復0
MetaverseHermitvip
· 07-16 18:32
精算决定生死门
回復0
BlockchainBardvip
· 07-16 18:31
精度问题值得关注
回復0
交易,隨時隨地
qrCode
掃碼下載 Gate APP
社群列表
繁體中文
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)