📢 Gate广场独家活动: #PUBLIC创作大赛# 正式开启!
参与 Gate Launchpool 第 297 期 — PublicAI (PUBLIC),并在 Gate广场发布你的原创内容,即有机会瓜分 4,000 枚 $PUBLIC 奖励池!
🎨 活动时间
2025年8月18日 10:00 – 2025年8月22日 16:00 (UTC)
📌 参与方式
在 Gate广场发布与 PublicAI (PUBLIC) 或当前 Launchpool 活动相关的原创内容
内容需不少于 100 字(可为分析、教程、创意图文、测评等)
添加话题: #PUBLIC创作大赛#
帖子需附带 Launchpool 参与截图(如质押记录、领取页面等)
🏆 奖励设置(总计 4,000 枚 $PUBLIC)
🥇 一等奖(1名):1,500 $PUBLIC
🥈 二等奖(3名):每人 500 $PUBLIC
🥉 三等奖(5名):每人 200 $PUBLIC
📋 评选标准
内容质量(相关性、清晰度、创意性)
互动热度(点赞、评论)
含有 Launchpool 参与截图的帖子将优先考虑
📄 注意事项
所有内容须为原创,严禁抄袭或虚假互动
获奖用户需完成 Gate广场实名认证
Gate 保留本次活动的最终解释权
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智能合约中数值计算的精度和可靠性。