📢 Gate廣場 #创作者活动第一期# 火熱開啓,助力 PUMP 公募上線!
Solana 爆火項目 Pump.Fun($PUMP)現已登入 Gate 平台開啓公開發售!
參與 Gate廣場創作者活動,釋放內容力量,贏取獎勵!
📅 活動時間:7月11日 18:00 - 7月15日 22:00(UTC+8)
🎁 活動總獎池:$500 USDT 等值代幣獎勵
✅ 活動一:創作廣場貼文,贏取優質內容獎勵
📅 活動時間:2025年7月12日 22:00 - 7月15日 22:00(UTC+8)
📌 參與方式:在 Gate 廣場發布與 PUMP 項目相關的原創貼文
內容不少於 100 字
必須帶上話題標籤: #创作者活动第一期# #PumpFun#
🏆 獎勵設置:
一等獎(1名):$100
二等獎(2名):$50
三等獎(10名):$10
📋 評選維度:Gate平台相關性、內容質量、互動量(點讚+評論)等綜合指標;參與認購的截圖的截圖、經驗分享優先;
✅ 活動二:發推同步傳播,贏傳播力獎勵
📌 參與方式:在 X(推特)上發布與 PUMP 項目相關內容
內容不少於 100 字
使用標籤: #PumpFun # Gate
發布後填寫登記表登記回鏈 👉 https://www.gate.com/questionnaire/6874
🏆 獎勵設置:傳播影響力前 10 名用戶,瓜分 $2
Rust智能合約數值精算:避坑指南與最佳實踐
Rust智能合約中的數值精算
在智能合約編程中,數值計算的精度問題尤爲重要。本文將探討Rust智能合約中常見的數值精算問題及解決方案。
1. 浮點數運算的精度問題
Rust語言原生支持浮點數運算,但浮點數運算存在無法避免的計算精度問題。在處理涉及重要經濟/金融決策的比率或利率時,不推薦使用浮點數運算。
Rust語言中的雙精度浮點類型f64遵循IEEE 754標準,採用底數爲2的科學計數法表示。某些小數(如0.7)無法用有限位長的浮點數準確表示,會存在"舍入"現象。
例如,在NEAR公鏈上分發0.7個NEAR代幣給10位用戶時:
rust let amount: f64 = 0.7;
let divisor: f64 = 10.0;
let result_0 = amount / divisor;
amount的實際值爲0.69999999999999995559,result_0的結果爲0.06999999999999999,而非預期的0.07。
爲解決這個問題,可以考慮使用定點數表示法。在NEAR Protocol中,通常使用10^24作爲分母,即1 NEAR = 10^24 yoctoNEAR。修改後的計算方式如下:
rust let N: u128 = 1_000_000_000_000_000_000_000_000;
let amount: u128 = 700_000_000_000_000_000_000_000; let divisor: u128 = 10;
let result_0 = amount / divisor;
這樣可以獲得精確的運算結果: 0.7 NEAR / 10 = 0.07 NEAR。
2. Rust整數計算精度的問題
使用整數計算雖然可以解決某些場景下的浮點數精度問題,但仍存在一些影響計算精度的因素。
2.1 運算順序
同一算數優先級的乘法與除法,其前後順序的變化可能直接影響計算結果。例如:
rust let a: u128 = 1_0000; let b: u128 = 10_0000; let c: u128 = 20;
// result_0 = a * c / b let result_0 = a.checked_mul(c).expect("ERR_MUL").checked_div(b).expect("ERR_DIV");
// result_1 = a / b * c let result_1 = a.checked_div(b).expect("ERR_DIV").checked_mul(c).expect("ERR_MUL");
result_0和result_1的計算結果不同,原因是整數除法會舍棄小於除數的精度。
2.2 過小的數量級
當涉及較小數量級的計算時,也可能導致精度問題:
rust let a: u128 = 10; let b: u128 = 3; let c: u128 = 4; let decimal: u128 = 100_0000;
// result_0 = (a / b) * c let result_0 = a.checked_div(b).expect("ERR_DIV").checked_mul(c).expect("ERR_MUL");
// result_1 = (a * decimal / b) * c / decimal;
let result_1 = a.checked_mul(decimal).expect("ERR_MUL") .checked_div(b).expect("ERR_DIV") .checked_mul(c).expect("ERR_MUL") .checked_div(decimal).expect("ERR_DIV");
result_0和result_1的運算結果不同,且result_1更接近實際預期值。
3. 如何編寫數值精算的Rust智能合約
爲提高Rust智能合約中的數值計算精度,可採取以下措施:
3.1 調整運算的操作順序
讓整數乘法優先於整數的除法。
3.2 增加整數的數量級
使用更大的數量級創造更大的分子,提高運算精度。
3.3 積累運算精度的損失
對於無法避免的整數計算精度問題,可以考慮記錄累計的運算精度損失。例如:
rust const USER_NUM: u128 = 3;
fn distribute(amount: u128, offset: u128) -> u128 { let token_to_distribute = offset + amount; let per_user_share = token_to_distribute / USER_NUM; let recorded_offset = token_to_distribute - per_user_share * USER_NUM; recorded_offset }
這種方法可以在多輪分發中逐步補償精度損失。
3.4 使用Rust Crate庫rust-decimal
該庫適用於需要有效精度計算和沒有舍入誤差的小數金融計算。
3.5 考慮舍入機制
在設計智能合約時,舍入問題通常遵循"我要佔便宜,他人不得薅我羊毛"的原則。根據情況選擇向下取整、向上取整或四舍五入。
通過採用這些方法,可以顯著提高Rust智能合約中數值計算的精度和可靠性。