Perhitungan nilai kontrak pintar Rust: Panduan menghindari kesalahan dan praktik terbaik

Perhitungan Presisi Numerik dalam Smart Contract Rust

Dalam pemrograman smart contract, masalah presisi perhitungan numerik sangat penting. Artikel ini akan membahas masalah akuntansi numerik yang umum dalam smart contract Rust dan solusi yang ada.

1. Masalah presisi dalam perhitungan angka desimal

Bahasa Rust secara native mendukung operasi bilangan pecahan, tetapi operasi bilangan pecahan memiliki masalah presisi perhitungan yang tidak dapat dihindari. Saat menangani rasio atau suku bunga yang melibatkan keputusan ekonomi/keuangan penting, tidak disarankan untuk menggunakan operasi bilangan pecahan.

Tipe floating point ganda f64 dalam bahasa Rust mengikuti standar IEEE 754, menggunakan notasi ilmiah dengan basis 2. Beberapa desimal ( seperti 0.7) tidak dapat direpresentasikan secara akurat dengan bilangan floating point dengan panjang terbatas, yang akan mengakibatkan fenomena "pembulatan".

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

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

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

Untuk menyelesaikan masalah ini, Anda dapat mempertimbangkan menggunakan representasi bilangan tetap. Di NEAR Protocol, biasanya menggunakan 10^24 sebagai penyebut, yaitu 1 NEAR = 10^24 yoctoNEAR. Cara perhitungan yang dimodifikasi adalah sebagai berikut:

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

Meskipun menggunakan perhitungan bilangan bulat dapat menyelesaikan masalah presisi bilangan pecahan dalam beberapa skenario, masih ada beberapa faktor yang mempengaruhi ketepatan perhitungan.

2.1 Urutan Operasi

Urutan perubahan antara 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, alasannya adalah bahwa pembagian bilangan bulat akan mengabaikan presisi yang lebih kecil dari pembagi.

2.2 skala yang terlalu kecil

Ketika melibatkan perhitungan dalam skala yang lebih kecil, juga dapat menyebabkan masalah akurasi:

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 operasi result_0 dan result_1 berbeda, dan result_1 lebih mendekati nilai harapan yang sebenarnya.

3. Bagaimana Menulis Kontrak Pintar Rust untuk Aktuaria Numerik

Untuk meningkatkan akurasi perhitungan numerik dalam smart contract Rust, langkah-langkah berikut dapat diambil:

3.1 Menyesuaikan urutan operasi perhitungan

Biarkan perkalian bilangan bulat diutamakan dibandingkan pembagian bilangan bulat.

3.2 Menambah Besaran Bilangan Bulat

Gunakan skala yang lebih besar untuk menciptakan molekul yang lebih besar, meningkatkan akurasi perhitungan.

3.3 Kerugian presisi akumulasi operasi

Untuk masalah presisi perhitungan integer yang tidak dapat dihindari, Anda dapat mempertimbangkan untuk mencatat akumulasi kehilangan presisi perhitungan. Misalnya:

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 }

Metode ini dapat secara bertahap mengkompensasi kehilangan akurasi dalam distribusi multi-putaran.

( 3.4 Menggunakan pustaka Rust Crate rust-decimal

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

) 3.5 Mempertimbangkan mekanisme pembulatan

Dalam merancang smart contract, masalah pembulatan biasanya mengikuti prinsip "Saya ingin mengambil keuntungan, orang lain tidak boleh mengambil keuntungan dari saya". Pilih untuk membulatkan ke bawah, membulatkan ke atas, atau membulatkan sesuai kebutuhan.

Dengan mengadopsi metode ini, akurasi dan keandalan perhitungan numerik dalam kontrak pintar Rust dapat meningkat secara signifikan.

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

B-0.27%
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
  • 5
  • Bagikan
Komentar
0/400
CrossChainBreathervip
· 07-16 01:40
Operasi titik mengambang itu omong kosong
Lihat AsliBalas0
CantAffordPancakevip
· 07-15 09:39
Jangan sebutkan tentang presisi, akunku sudah nol.
Lihat AsliBalas0
MaticHoleFillervip
· 07-13 03:03
Sepanjang hari terjebak dalam masalah presisi, kehilangan usaha percuma.
Lihat AsliBalas0
StablecoinAnxietyvip
· 07-13 02:58
Sedikit pusing karena harus mengurus algoritme dan keuangan~
Lihat AsliBalas0
GhostAddressMinervip
· 07-13 02:34
Satu lagi kasus klasik pengalihan masalah presisi kepada standar, secara diam-diam tidak tahu berapa banyak dana yang telah dicairkan, data on-chain tidak akan berbohong.
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)