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.
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.
13 Suka
Hadiah
13
5
Bagikan
Komentar
0/400
CrossChainBreather
· 07-16 01:40
Operasi titik mengambang itu omong kosong
Lihat AsliBalas0
CantAffordPancake
· 07-15 09:39
Jangan sebutkan tentang presisi, akunku sudah nol.
Lihat AsliBalas0
MaticHoleFiller
· 07-13 03:03
Sepanjang hari terjebak dalam masalah presisi, kehilangan usaha percuma.
Lihat AsliBalas0
StablecoinAnxiety
· 07-13 02:58
Sedikit pusing karena harus mengurus algoritme dan keuangan~
Lihat AsliBalas0
GhostAddressMiner
· 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.
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###