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.
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
7 Suka
Hadiah
7
3
Bagikan
Komentar
0/400
MaticHoleFiller
· 10jam yang lalu
Sepanjang hari terjebak dalam masalah presisi, kehilangan usaha percuma.
Lihat AsliBalas0
StablecoinAnxiety
· 10jam yang lalu
Sedikit pusing karena harus mengurus algoritme dan keuangan~
Lihat AsliBalas0
GhostAddressMiner
· 11jam yang lalu
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###