Akıllı sözleşmeler programlamasında, sayısal hesaplamaların hassasiyeti oldukça önemlidir. Bu makalede, Rust akıllı sözleşmelerinde yaygın olarak karşılaşılan sayısal hesaplama sorunları ve çözüm önerileri incelenecektir.
1. Ondalık sayı hesaplamalarının hassasiyet sorunu
Rust dili, kayan nokta hesaplamalarını yerel olarak destekler, ancak kayan nokta hesaplamalarının kaçınılmaz hesaplama hassasiyeti sorunları vardır. Önemli ekonomik/finansal kararlarla ilgili oranlar veya faiz oranlarıyla ilgili işlemler yaparken, kayan nokta hesaplamalarının kullanılmasını önermiyoruz.
Rust dilindeki çift hassasiyetli kayan nokta türü f64, IEEE 754 standardını takip eder ve tabanı 2 olan bilimsel gösterim kullanır. Bazı ondalık sayılar ( gibi 0.7), sınırlı uzunluktaki kayan nokta sayılarıyla doğru bir şekilde temsil edilemez ve "yuvarlama" olayı meydana gelebilir.
Örneğin, NEAR blok zincirinde 10 kullanıcıya 0.7 NEAR token dağıtıldığında:
pas
let amount: f64 = 0.7;
let divisor: f64 = 10.0;
let result_0 = amount / divisor;
amount'ın gerçek değeri 0.69999999999999995559, result_0'ın sonucu ise 0.06999999999999999, beklenen 0.07 değil.
Bu sorunu çözmek için, sabit noktalı sayı gösterimini kullanmayı düşünebilirsiniz. NEAR Protokolü'nde genellikle 10^24 payda olarak kullanılır, yani 1 NEAR = 10^24 yoctoNEAR. Değiştirilmiş hesaplama yöntemi aşağıdaki gibidir:
pas
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;
Bu şekilde kesin hesaplama sonucu elde edilebilir: 0.7 NEAR / 10 = 0.07 NEAR.
2. Rust tamsayı hesaplama hassasiyeti sorunu
Tam sayılarla hesaplama yapmak bazı senaryolardaki ondalık sayı hassasiyeti sorunlarını çözse de, hesaplama hassasiyetini etkileyen bazı faktörler hala mevcuttur.
2.1 İşlem Sırası
Aynı aritmetik önceliğe sahip çarpma ve bölme işlemlerinin sırası, hesaplama sonucunu doğrudan etkileyebilir. Örneğin:
pas
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");
result_0 ile result_1'in hesaplama sonuçları farklı, nedeni tam sayı bölmesinin paydadan küçük olan hassasiyeti göz ardı etmesidir.
2.2 çok küçük bir ölçek
Küçük ölçekli hesaplamalar söz konusu olduğunda, hassasiyet sorunlarına da yol açabilir:
pas
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 * ondalık / b) * c / ondalık;
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");
result_0 ve result_1'in hesaplama sonuçları farklı ve result_1 gerçek beklenen değere daha yakın.
3. Sayısal Aktüerya için Rust akıllı sözleşmeler nasıl yazılır
Rust akıllı sözleşmelerindeki sayısal hesaplama hassasiyetini artırmak için aşağıdaki önlemler alınabilir:
3.1 İşlem sırasını ayarlama
Tam sayı çarpımının tam sayı bölmeden öncelikli olmasını sağla.
3.2 tam sayıların büyüklüğünü artır
Daha büyük bir ölçek kullanarak daha büyük moleküller oluşturun ve hesaplama hassasiyetini artırın.
3.3 Hesaplama hassasiyetinin kaybı
Kaçınılmaz tam sayı hesaplama hassasiyeti sorunları için, birikmiş hesaplama hassasiyeti kaybını kaydetmeyi düşünebilirsiniz. Örneğin:
pas
const USER_NUM: u128 = 3;
u128 {
let dağıtılacak_token = offset + amount;
let per_user_share = token_to_distribute / USER_NUM;
let recorded_offset = token_to_distribute - per_user_share * USER_NUM;
kaydedilen_offset
}
Bu yöntem, çoklu dağıtımda hassasiyet kaybını kademeli olarak telafi edebilir.
( 3.4 Rust Crate kütüphanesi rust-decimal kullanımı
Bu kütüphane, hassas hesaplamalar ve yuvarlama hatası olmayan ondalık finansal hesaplamalar için uygundur.
) 3.5 Yuvarlama mekanizmasını göz önünde bulundurun
Akıllı sözleşmeler tasarlarken, yuvarlama sorunları genellikle "Ben avantaj sağlamalıyım, diğerleri benim kazancımı alamaz" ilkesine göre hareket eder. Duruma göre aşağı yuvarlama, yukarı yuvarlama veya en yakın tam sayıya yuvarlama yapılır.
Bu yöntemleri kullanarak, Rust akıllı sözleşmelerindeki sayısal hesaplamaların doğruluğunu ve güvenilirliğini önemli ölçüde artırabilirsiniz.
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 Likes
Reward
7
3
Share
Comment
0/400
MaticHoleFiller
· 17h ago
Tüm gün hassasiyet sorununda takılı kalmak, boşuna kaybetmek.
View OriginalReply0
StablecoinAnxiety
· 17h ago
Hem algoritma hem finans olması biraz kafa karıştırıcı~
View OriginalReply0
GhostAddressMiner
· 17h ago
Bir başka hassasiyet sorununu standartlara atma konusunda tipik bir örnek, gizlice ne kadar fonun bozdurulduğunu bilmeyen, on-chain veriler yalan söylemeyecek.
Rust akıllı sözleşmeler değer hesaplaması: tuzaklardan kaçınma rehberi ve en iyi uygulamalar
Rust akıllı sözleşmelerindeki sayısal hesaplamalar
Akıllı sözleşmeler programlamasında, sayısal hesaplamaların hassasiyeti oldukça önemlidir. Bu makalede, Rust akıllı sözleşmelerinde yaygın olarak karşılaşılan sayısal hesaplama sorunları ve çözüm önerileri incelenecektir.
1. Ondalık sayı hesaplamalarının hassasiyet sorunu
Rust dili, kayan nokta hesaplamalarını yerel olarak destekler, ancak kayan nokta hesaplamalarının kaçınılmaz hesaplama hassasiyeti sorunları vardır. Önemli ekonomik/finansal kararlarla ilgili oranlar veya faiz oranlarıyla ilgili işlemler yaparken, kayan nokta hesaplamalarının kullanılmasını önermiyoruz.
Rust dilindeki çift hassasiyetli kayan nokta türü f64, IEEE 754 standardını takip eder ve tabanı 2 olan bilimsel gösterim kullanır. Bazı ondalık sayılar ( gibi 0.7), sınırlı uzunluktaki kayan nokta sayılarıyla doğru bir şekilde temsil edilemez ve "yuvarlama" olayı meydana gelebilir.
Örneğin, NEAR blok zincirinde 10 kullanıcıya 0.7 NEAR token dağıtıldığında:
pas let amount: f64 = 0.7;
let divisor: f64 = 10.0;
let result_0 = amount / divisor;
amount'ın gerçek değeri 0.69999999999999995559, result_0'ın sonucu ise 0.06999999999999999, beklenen 0.07 değil.
Bu sorunu çözmek için, sabit noktalı sayı gösterimini kullanmayı düşünebilirsiniz. NEAR Protokolü'nde genellikle 10^24 payda olarak kullanılır, yani 1 NEAR = 10^24 yoctoNEAR. Değiştirilmiş hesaplama yöntemi aşağıdaki gibidir:
pas 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;
Bu şekilde kesin hesaplama sonucu elde edilebilir: 0.7 NEAR / 10 = 0.07 NEAR.
2. Rust tamsayı hesaplama hassasiyeti sorunu
Tam sayılarla hesaplama yapmak bazı senaryolardaki ondalık sayı hassasiyeti sorunlarını çözse de, hesaplama hassasiyetini etkileyen bazı faktörler hala mevcuttur.
2.1 İşlem Sırası
Aynı aritmetik önceliğe sahip çarpma ve bölme işlemlerinin sırası, hesaplama sonucunu doğrudan etkileyebilir. Örneğin:
pas 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");
result_0 ile result_1'in hesaplama sonuçları farklı, nedeni tam sayı bölmesinin paydadan küçük olan hassasiyeti göz ardı etmesidir.
2.2 çok küçük bir ölçek
Küçük ölçekli hesaplamalar söz konusu olduğunda, hassasiyet sorunlarına da yol açabilir:
pas 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 * ondalık / b) * c / ondalık; 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");
result_0 ve result_1'in hesaplama sonuçları farklı ve result_1 gerçek beklenen değere daha yakın.
3. Sayısal Aktüerya için Rust akıllı sözleşmeler nasıl yazılır
Rust akıllı sözleşmelerindeki sayısal hesaplama hassasiyetini artırmak için aşağıdaki önlemler alınabilir:
3.1 İşlem sırasını ayarlama
Tam sayı çarpımının tam sayı bölmeden öncelikli olmasını sağla.
3.2 tam sayıların büyüklüğünü artır
Daha büyük bir ölçek kullanarak daha büyük moleküller oluşturun ve hesaplama hassasiyetini artırın.
3.3 Hesaplama hassasiyetinin kaybı
Kaçınılmaz tam sayı hesaplama hassasiyeti sorunları için, birikmiş hesaplama hassasiyeti kaybını kaydetmeyi düşünebilirsiniz. Örneğin:
pas const USER_NUM: u128 = 3;
u128 { let dağıtılacak_token = offset + amount; let per_user_share = token_to_distribute / USER_NUM; let recorded_offset = token_to_distribute - per_user_share * USER_NUM; kaydedilen_offset }
Bu yöntem, çoklu dağıtımda hassasiyet kaybını kademeli olarak telafi edebilir.
( 3.4 Rust Crate kütüphanesi rust-decimal kullanımı
Bu kütüphane, hassas hesaplamalar ve yuvarlama hatası olmayan ondalık finansal hesaplamalar için uygundur.
) 3.5 Yuvarlama mekanizmasını göz önünde bulundurun
Akıllı sözleşmeler tasarlarken, yuvarlama sorunları genellikle "Ben avantaj sağlamalıyım, diğerleri benim kazancımı alamaz" ilkesine göre hareket eder. Duruma göre aşağı yuvarlama, yukarı yuvarlama veya en yakın tam sayıya yuvarlama yapılır.
Bu yöntemleri kullanarak, Rust akıllı sözleşmelerindeki sayısal hesaplamaların doğruluğunu ve güvenilirliğini önemli ölçüde artırabilirsiniz.
![]###https://img-cdn.gateio.im/webp-social/moments-6e8b4081214a69423fc7ae022d05c728.webp###