📢 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智能合约开发中的数值计算精度问题
1. 浮点数运算的精度问题
Rust语言原生支持浮点数运算,但浮点数运算存在无法避免的计算精度问题。在编写智能合约时,不推荐使用浮点数运算,尤其是处理重要经济/金融决策的比率或利率时。
Rust语言中双精度浮点类型f64遵循IEEE 754标准,采用底数为2的科学计数法表达。某些小数无法用有限位长的浮点数准确表示,存在"舍入"现象。
例如,在NEAR公链上分发0.7个NEAR代币给10位用户时:
rust #[test] fn precision_test_float() { let amount: f64 = 0.7;
let divisor: f64 = 10.0;
let result_0 = amount / divisor;
println!("The value of amount: {:.20}", amount); assert_eq!(result_0, 0.07, ""); }
输出结果显示amount的值为0.69999999999999995559,不是准确的0.7。除法运算结果也变为不精确的0.06999999999999999,而非预期的0.07。
为解决这个问题,可以考虑使用定点数。在NEAR Protocol中,常用10^24个yoctoNEAR表示1个NEAR代币。修改后的测试代码:
rust #[test] fn precision_test_integer() { 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; assert_eq!(result_0, 70_000_000_000_000_000_000_000, ""); }
这样可以获得精确的运算结果: 0.7 NEAR / 10 = 0.07 NEAR。
2. Rust整数计算精度的问题
使用整数运算可解决某些场景中浮点数运算的精度丢失问题,但整数计算结果也并非完全准确可靠。
2.1 运算顺序
同一算数优先级的乘法与除法,其前后顺序的变化可能直接影响计算结果,导致整数计算精度问题。例如:
rust #[test] fn precision_test_div_before_mul() { let a: u128 = 1_0000; let b: u128 = 10_0000; let c: u128 = 20;
}
执行结果显示result_0和result_1不相等。原因是整数除法会舍弃小于除数的精度。计算result_1时,(a / b)先失去精度变为0;而计算result_0时,先算a * c避免了精度丢失。
2.2 过小的数量级
当涉及小数计算时,整数运算可能导致精度丢失:
rust #[test] fn precision_test_decimals() { let a: u128 = 10; let b: u128 = 3; let c: u128 = 4; let decimal: u128 = 100_0000;
}
结果显示result_0=12,result_1=13,而实际预期值应为13.3333....
3. 如何编写数值精算的Rust智能合约
为提高精度,可采取以下防护手段:
3.1 调整运算的操作顺序
让整数乘法优先于整数的除法。
3.2 增加整数的数量级
使用更大的数量级,创造更大的分子。例如,表示5.123 NEAR可用5.123 * 10^10 = 51_230_000_000参与后续运算。
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; println!("per_user_share {}", per_user_share); let recorded_offset = token_to_distribute - per_user_share * USER_NUM; recorded_offset }
#[test] fn record_offset_test() { let mut offset: u128 = 0; for i in 1..7 { println!("Round {}", i); offset = distribute(to_yocto("10"), offset); println!("Offset {}\n", offset); } }
这种方法可以将每次分发剩余的token累积起来,在下次分发时一并发放,最终达到足额发放的目的。
3.4 使用Rust Crate库rust-decimal
该库适用于需要有效精度计算和没有舍入误差的小数金融计算。
3.5 考虑舍入机制
在智能合约设计中,舍入问题通常采用"我要占便宜,他人不得薅我羊毛"的原则。根据情况选择向下取整或向上取整,极少采用四舍五入。