Masalah presisi operasi numerik dan solusi optimasi dalam kontrak pintar Rust

robot
Pembuatan abstrak sedang berlangsung

Buku Harian Pengembangan Smart Contract Rust (7) Masalah Presisi Operasi Bilangan Pecahan dan Bilangan Bulat

Artikel ini akan membahas masalah presisi operasi angka floating point dan integer dalam smart contract Rust, serta bagaimana menulis smart contract untuk perhitungan numerik.

1. Masalah Presisi dalam Operasi Bilangan Desimal

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

Dalam bahasa Rust, angka desimal menggunakan standar IEEE 754 dan diwakili dalam notasi ilmiah dengan basis 2. Beberapa desimal seperti ( dan 0.7) tidak dapat secara akurat diwakili dengan angka desimal terbatas, sehingga akan ada fenomena "pembulatan".

Misalnya, saat mendistribusikan 0,7 token NEAR kepada 10 pengguna di blockchain NEAR:

karat #[test] fn precision_test_float() { let amount: f64 = 0.7;
let divisor: f64 = 10.0;
let result_0 = amount / divisor;
assert_eq!(result_0, 0.07, ""); }

Hasil eksekusi menunjukkan bahwa nilai amount bukanlah 0.7 yang akurat, melainkan nilai mendekati 0.69999999999999995559. Hasil operasi pembagian juga tidak akurat, yaitu 0.06999999999999999 dan bukan 0.07 yang diharapkan.

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

karat #[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, ""); }

Dengan cara ini, dapatkan hasil perhitungan nilai aktuaria: 0,7 NEAR / 10 = 0,07 NEAR.

2. Masalah Presisi Perhitungan Integer Rust

2.1 Urutan Operasi

Urutan antara perkalian dan pembagian dengan prioritas aritmetika yang sama dapat secara langsung mempengaruhi hasil perhitungan.

karat #[test] fn precision_test_div_before_mul() { let a: u128 = 1_0000; let b: u128 = 10_0000; let c: u128 = 20;

let result_0 = a.checked_mul(c).expect("ERR_MUL")
                .checked_div(b).expect("ERR_DIV");

let result_1 = a.checked_div(b).expect("ERR_DIV")
                .checked_mul(c).expect("ERR_MUL");

assert_eq!(result_0,result_1,"");

}

Hasil eksekusi menunjukkan bahwa result_0 dan result_1 tidak sama. Alasannya adalah pembagian bilangan bulat akan mengabaikan presisi yang kurang dari penyebut. Saat menghitung result_1, (a / b) akan kehilangan presisi menjadi 0; sedangkan saat menghitung result_0, menghitung a * c terlebih dahulu dapat menghindari kehilangan presisi.

2.2 skala yang terlalu kecil

Besaran yang terlalu kecil juga dapat menyebabkan masalah akurasi:

karat #[test] fn precision_test_decimals() { let a: u128 = 10; let b: u128 = 3; let c: u128 = 4; let decimal: u128 = 100_0000;

let result_0 = a.checked_div(b).expect("ERR_DIV")
                .checked_mul(c).expect("ERR_MUL");

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

assert_eq!(result_0, result_1, "");

}

Hasil menunjukkan result_0=12, result_1=13, yang terakhir lebih dekat dengan nilai yang diharapkan 13.3333.

3. Cara Menulis Kontrak Pintar Rust untuk Aktuaria Numerik

Untuk meningkatkan akurasi, langkah-langkah perlindungan berikut dapat diambil:

3.1 Menyesuaikan urutan operasi perhitungan

Mengutamakan perkalian integer dibandingkan pembagian integer.

3.2 meningkatkan urutan bilangan bulat

Gunakan skala yang lebih besar untuk menciptakan molekul yang lebih besar. Misalnya, nyatakan 5.123 NEAR sebagai 5.123 * 10^10 = 51_230_000_000.

3.3 kehilangan akurasi operasi akumulasi

Mencatat kehilangan presisi perhitungan yang terakumulasi:

karat const USER_NUM: u128 = 3;

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 }

#( fn record_offset_test)[test] { let mut offset: u128 = 0; untuk i dalam 1..7 { offset = distribute(to_yocto)"10"(, offset(; } }

Dengan cara ini, token yang tidak terdistribusi dapat disimpan sementara, dan akan dibagikan bersama saat distribusi berikutnya.

) 3.4 Menggunakan pustaka Rust Crate rust-decimal

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

) 3.5 Pertimbangkan mekanisme pembulatan

Dalam merancang smart contract, biasanya digunakan prinsip "Saya ingin mengambil keuntungan, orang lain tidak boleh memanfaatkan saya." Pilih untuk membulatkan ke bawah atau ke atas sesuai situasi, sangat jarang menggunakan pembulatan.

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

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
  • 6
  • Bagikan
Komentar
0/400
GhostInTheChainvip
· 07-15 16:28
rust masih perlu mengisi desimal... tidak mudah
Lihat AsliBalas0
BoredWatchervip
· 07-13 18:40
Apakah pustaka rust dapat menulis kontrak?
Lihat AsliBalas0
GasFeeNightmarevip
· 07-13 18:35
Akurasi perhitungan sama menjengkelkannya seperti biaya gas saya...
Lihat AsliBalas0
EyeOfTheTokenStormvip
· 07-13 18:34
Tingkat kehilangan presisi secara langsung mempengaruhi rasio untung rugi, siapa yang masih menggunakan bilangan floating point untuk kuantifikasi? Para penjudi sudah Rug Pull, kan?
Lihat AsliBalas0
TokenEconomistvip
· 07-13 18:32
sebenarnya, kehilangan presisi = f(pesanan_ops, faktor_skala) ... pustaka rust-decimal untuk menang!
Lihat AsliBalas0
just_another_walletvip
· 07-13 18:25
Angka desimal terlalu merepotkan ya...
Lihat AsliBalas0
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)