Développement de smart contracts en Rust : techniques de calcul numérique et de contrôle de la précision

Journal de développement des smart contracts en Rust (7) : Calcul numérique

1. Problème de précision dans les calculs en virgule flottante

Le langage Rust prend en charge nativement les opérations sur les nombres à virgule flottante, mais ces opérations présentent des problèmes de précision de calcul inévitables. Lors de la rédaction de smart contracts, il est déconseillé d'utiliser des opérations sur les nombres à virgule flottante, en particulier lors du traitement de ratios ou de taux d'intérêt impliquant des décisions économiques/financières importantes.

Le type de nombre à virgule flottante en double précision f64 dans le langage Rust suit la norme IEEE 754 et utilise une notation scientifique en base 2. Certains décimales comme 0.7 ne peuvent pas être représentées avec précision par un nombre à virgule flottante de longueur finie, ce qui entraîne un phénomène d'"arrondi".

Lors d'un test de distribution de 0,7 NEAR tokens à dix utilisateurs sur la blockchain NEAR, le résultat des opérations flottantes n'est pas précis :

rouille let amount: f64 = 0.7;
let divisor: f64 = 10.0; let result_0 = amount / divisor;

la valeur de amount est de 0.69999999999999995559, la valeur de result_0 est de 0.06999999999999999, au lieu de l'attendu 0.07.

Pour résoudre ce problème, on peut utiliser des nombres à virgule fixe. Dans le protocole NEAR, on utilise généralement la manière suivante pour représenter : 1 NEAR = 10^24 yoctoNEAR.

rouille 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;

Cela permet d'obtenir un résultat de calcul précis : 0,7 NEAR / 10 = 0,07 NEAR.

2. Problèmes de précision des calculs d'entiers en Rust

2.1 ordre des opérations

Dans les opérations de multiplication et de division ayant la même priorité arithmétique, l'ordre des opérations peut directement influencer le résultat du calcul. Par exemple :

rouille 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");

Les résultats de result_0 et result_1 sont différents, car pour la division entière, la précision inférieure au diviseur sera abandonnée.

2.2 trop petit ordre de grandeur

Lorsqu'il s'agit de petites valeurs, les opérations sur les entiers peuvent entraîner une perte de précision:

rouille 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");

Le résultat de result_0 et result_1 est différent, result_1 est plus proche de la valeur attendue réelle.

3. Comment écrire des smart contracts Rust pour l'évaluation numérique

3.1 Ajuster l'ordre des opérations

Faire en sorte que la multiplication entière prenne priorité sur la division entière.

3.2 augmenter l'ordre de grandeur des entiers

Utiliser une plus grande échelle pour créer des molécules plus grandes. Par exemple, représenter 5,123 NEAR comme 51_230_000_000 yoctoNEAR.

3.3 perte de précision des opérations d'accumulation

Enregistrer la perte de précision des calculs cumulés et la compenser dans les calculs ultérieurs. Par exemple :

rouille 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 Utilisation de la bibliothèque Rust Crate rust-decimal

Cette bibliothèque est adaptée aux calculs financiers décimaux nécessitant une précision efficace et sans erreur d'arrondi.

) 3.5 Considérer le mécanisme d'arrondi

Dans la conception de smart contracts, le problème d'arrondi est généralement basé sur le principe "Je veux en profiter, les autres ne doivent pas me tondre la laine sur le dos". En fonction de la situation, choisissez l'arrondi vers le bas, l'arrondi vers le haut ou l'arrondi classique.

![]###https://img-cdn.gateio.im/webp-social/moments-6e8b4081214a69423fc7ae022d05c728.webp###

TOKEN3.1%
NUM1.39%
Voir l'original
Cette page peut inclure du contenu de tiers fourni à des fins d'information uniquement. Gate ne garantit ni l'exactitude ni la validité de ces contenus, n’endosse pas les opinions exprimées, et ne fournit aucun conseil financier ou professionnel à travers ces informations. Voir la section Avertissement pour plus de détails.
  • Récompense
  • 3
  • Partager
Commentaire
0/400
BearMarketBuildervip
· 08-05 07:58
Le trou des nombres à virgule flottante est tout simplement aussi profond que la mer.
Voir l'originalRépondre0
SelfSovereignStevevip
· 08-05 07:53
Les nombres à virgule flottante sont vraiment problématiques, les smart contracts vont forcément échouer, je n'ose absolument pas les utiliser.
Voir l'originalRépondre0
DegenGamblervip
· 08-05 07:49
Joueurs de Rust, faites attention, le piège de la précision n'est pas petit.
Voir l'originalRépondre0
  • Épingler
Trader les cryptos partout et à tout moment
qrCode
Scan pour télécharger Gate app
Communauté
Français (Afrique)
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)