🎉 親愛的廣場小夥伴們,福利不停,精彩不斷!目前廣場上這些熱門發帖贏獎活動火熱進行中,發帖越多,獎勵越多,快來 GET 你的專屬好禮吧!🚀
🆘 #Gate 2025年中社区盛典# |廣場十強內容達人評選
決戰時刻到!距離【2025年中社區盛典】廣場達人評選只剩 1 天,你喜愛的達人,就差你這一票衝進 C 位!在廣場發帖、點讚、評論就能攢助力值,幫 Ta 上榜的同時,你自己還能抽大獎!iPhone 16 Pro Max、金牛雕塑、潮流套裝、合約體驗券 等你抱走!
詳情 👉 https://www.gate.com/activities/community-vote
1️⃣ #晒出我的Alpha积分# |曬出 Alpha 積分&收益
Alpha 積分黨集合!帶話題曬出你的 Alpha 積分圖、空投中獎圖,即可瓜分 $200 Alpha 代幣盲盒,積分最高直接抱走 $100!分享攢分祕籍 / 兌換經驗,中獎率直線上升!
詳情 👉 https://www.gate.com/post/status/12763074
2️⃣ #ETH百万矿王争霸赛# |ETH 鏈上挖礦曬收益
礦工集結!帶話題曬出你的 Gate ETH 鏈上挖礦收益圖,瓜分 $400 曬圖獎池,收益榜第一獨享 $200!誰才是真 ETH 礦王?開曬見分曉!
詳情 👉 https://www.gate.com/pos
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智能合約中實現更加精確的數值計算,避免因精度問題而導致的錯誤或不公平結果。