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智能合约中实现更加精确的数值计算,避免因精度问题而导致的错误或不公平结果。

此页面可能包含第三方内容,仅供参考(非陈述/保证),不应被视为 Gate 认可其观点表述,也不得被视为财务或专业建议。详见声明
  • 赞赏
  • 8
  • 转发
  • 分享
评论
0/400
资深老韭当家vip
· 07-19 12:17
精度确实坑人
回复0
跑路预言家vip
· 07-18 09:14
精度把控要到位
回复0
Gas_Optimizervip
· 07-16 19:00
精度即是生命
回复0
测试网学者vip
· 07-16 18:56
去整数算更靠谱
回复0
gas费烧烤摊vip
· 07-16 18:46
比率乘以10000
回复0
GweiWatchervip
· 07-16 18:46
精度坑太多了
回复0
MetaverseHermitvip
· 07-16 18:32
精算决定生死门
回复0
BlockchainBardvip
· 07-16 18:31
精度问题值得关注
回复0
交易,随时随地
qrCode
扫码下载 Gate App
社群列表
简体中文
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)