「沒有對手?我有話說!」Gate廣場挑戰賽——秀操作贏$2,000,百萬流量加持!
你是下一個明星交易員嗎?
想讓自己的名字閃耀廣場熱搜?想吸引數萬追隨者?百萬流量已就位,就等你來承接!
🎉 雙重豪禮,贏家通喫!
1️⃣ 曬單排行榜獎勵
收益率排名前10的用戶,瓜分 $1,500合約體驗券!巔峯對決等你來戰!
2️⃣ 曬單幸運獎
隨機抽取10位用戶,每人贈送 $50跟單包賠券!即使不是大神,也有機會躺贏!
🎮 參與方式超簡單!
✅ 在 Gate廣場 曬出你的交易戰績,並成爲帶單員!
✨ 發帖要求:
內容必須原創,並帶上 #CopyTrading# 或 #跟单# 標籤
附上 收益率截圖 或 交易卡片,並分享你的 獨家交易心得
嚴禁AI生成虛假交易,一經發現取消資格
觀點犀利、邏輯清晰,乾貨越多越吸粉!
⏰ 活動截止:8月15日 10:00(UTC+8)
【立即發帖】 展現你的王者操作,承接百萬流量,成爲下一個交易傳奇!
💬 還在等什麼?Gate廣場,等你來戰! 💪
Rust智能合約開發:數值精算與精度控制技巧
Rust智能合約養成日記(7):數值精算
1. 浮點數運算的精度問題
Rust語言原生支持浮點數運算,但浮點數運算存在着無法避免的計算精度問題。在編寫智能合約時,不推薦使用浮點數運算,尤其是在處理涉及重要經濟/金融決策的比率或利率時。
Rust語言中的雙精度浮點類型f64遵循IEEE 754標準,採用底數爲2的科學計數法表達。某些小數如0.7無法用有限位長的浮點數準確表示,存在"舍入"現象。
在NEAR公鏈上分發0.7個NEAR代幣給十位用戶的測試中,浮點運算結果不精確:
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中,通常使用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智能合約
3.1 調整運算的操作順序
令整數乘法優先於整數的除法。
3.2 增加整數的數量級
使用更大的數量級,創造更大的分子。例如,將5.123 NEAR表示爲51_230_000_000 yoctoNEAR。
3.3 積累運算精度的損失
記錄累計的運算精度損失,在後續運算中補償。例如:
rust 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 考慮舍入機制
在智能合約設計中,舍入問題通常採用"我要佔便宜,他人不得薅我羊毛"的原則。根據情況選擇向下取整、向上取整或四舍五入。