Pengembangan smart contract Rust: Teknik perhitungan numerik dan kontrol presisi

Buku Harian Pengembangan smart contract Rust (7): Perhitungan Nilai

1. Masalah Presisi dalam Operasi Bilangan Desimal

Bahasa Rust secara native mendukung operasi bilangan floating-point, tetapi operasi bilangan floating-point memiliki masalah presisi perhitungan yang tidak dapat dihindari. Saat menulis smart contract, tidak disarankan untuk menggunakan operasi bilangan floating-point, terutama saat menangani rasio atau suku bunga yang melibatkan keputusan ekonomi/keuangan yang penting.

Tipe floating point presisi ganda f64 dalam bahasa Rust mengikuti standar IEEE 754, menggunakan notasi ilmiah dengan basis 2. Beberapa desimal seperti 0.7 tidak dapat diwakili secara akurat dengan floating point berukuran terbatas, yang menyebabkan fenomena "pembulatan".

Dalam pengujian distribusi 0,7 token NEAR kepada sepuluh pengguna di blockchain NEAR, hasil perhitungan floating point tidak akurat:

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

nilai amount adalah 0.69999999999999995559, nilai result_0 adalah 0.06999999999999999, bukan 0.07 seperti yang diharapkan.

Untuk mengatasi masalah ini, dapat digunakan bilangan tetap. Dalam NEAR Protocol, biasanya menggunakan cara 1 NEAR = 10^24 yoctoNEAR untuk menyatakannya:

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

Dengan cara ini, Anda dapat memperoleh hasil perhitungan yang akurat: 0,7 NEAR / 10 = 0,07 NEAR.

2. Masalah Presisi Perhitungan Integer Rust

2.1 Urutan Operasi

Urutan perubahan dari perkalian dan pembagian dengan prioritas aritmatika yang sama dapat langsung mempengaruhi hasil perhitungan. Contohnya:

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

Hasil dari result_0 dan result_1 berbeda, karena untuk pembagian bilangan bulat, presisi yang lebih kecil dari pembagi akan diabaikan.

2.2 skala yang terlalu kecil

Ketika berurusan dengan nilai desimal, operasi bilangan bulat dapat mengakibatkan kehilangan presisi:

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

Hasil dari result_0 dan result_1 berbeda, result_1 lebih mendekati nilai yang diharapkan.

3. Cara Menulis Kontrak Pintar Rust untuk Aktuaria Numerik

3.1 Menyesuaikan urutan operasi perhitungan

Memprioritaskan perkalian bilangan bulat dibandingkan dengan pembagian bilangan bulat.

3.2 Meningkatkan urutan angka bulat

Gunakan skala yang lebih besar untuk menciptakan molekul yang lebih besar. Misalnya, mewakili 5.123 NEAR sebagai 51_230_000_000 yoctoNEAR.

3.3 Kehilangan presisi akumulasi operasi

Mencatat kehilangan presisi perhitungan yang terakumulasi, dan mengompensasinya dalam perhitungan selanjutnya. Contoh:

karat 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 Menggunakan pustaka Rust Crate rust-decimal

Perpustakaan ini cocok untuk perhitungan keuangan desimal yang memerlukan akurasi yang efektif dan tidak memiliki kesalahan pembulatan.

) 3.5 Pertimbangkan mekanisme pembulatan

Dalam desain smart contract, masalah pembulatan biasanya mengikuti prinsip "Saya ingin mendapatkan keuntungan, orang lain tidak boleh memanfaatkan saya". Pilih untuk membulatkan ke bawah, membulatkan ke atas, atau pembulatan biasa sesuai situasi.

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

TOKEN3.04%
NUM2.08%
Lihat Asli
Halaman ini mungkin berisi konten pihak ketiga, yang disediakan untuk tujuan informasi saja (bukan pernyataan/jaminan) dan tidak boleh dianggap sebagai dukungan terhadap pandangannya oleh Gate, atau sebagai nasihat keuangan atau profesional. Lihat Penafian untuk detailnya.
  • Hadiah
  • 3
  • Bagikan
Komentar
0/400
BearMarketBuildervip
· 08-05 07:58
Lubang float ini benar-benar dalam seperti laut
Lihat AsliBalas0
SelfSovereignStevevip
· 08-05 07:53
Floating point number terlalu bermasalah, smart contract pasti meledak, sama sekali tidak berani menggunakannya.
Lihat AsliBalas0
DegenGamblervip
· 08-05 07:49
Para saudara yang bermain Rust, perhatikan, lubang presisi ini tidak kecil.
Lihat AsliBalas0
  • Sematkan
Perdagangkan Kripto Di Mana Saja Kapan Saja
qrCode
Pindai untuk mengunduh aplikasi Gate
Komunitas
Bahasa Indonesia
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)