Rust akıllı sözleşmeler geliştirme: Sayısal hesaplama hassasiyeti sorununu aşma

Rust akıllı sözleşmeler geliştirmedeki sayısal hesaplama hassasiyeti sorunları

1. Kesirli sayı işlemlerinin hassasiyet sorunu

Rust dilinin yerel olarak ondalık sayı işlemlerini desteklemesine rağmen, ondalık sayı işlemleri kaçınılmaz hesaplama hassasiyeti sorunları taşır. Akıllı sözleşmeler yazarken, özellikle önemli ekonomik/finansal kararların oranları veya faiz oranlarıyla ilgili işlemler yaparken ondalık sayı işlemlerinin kullanılmasını önerilmez.

Rust dilinde çift hassasiyetli kayan nokta türü f64, IEEE 754 standardını takip eder ve 2 tabanlı bilimsel gösterim kullanır. Bazı ondalık sayılar, sonlu uzunlukta kayan sayılarla kesin olarak temsil edilemez ve "yuvarlama" olayı vardır.

Örneğin, NEAR blok zincirinde 10 kullanıcıya 0.7 NEAR token dağıtıldığında:

pas #[test] fn precision_test_float() { let amount: f64 = 0.7;
let divisor: f64 = 10.0;
let result_0 = amount / divisor;
println!("Miktarın değeri: {:.20}", amount); assert_eq!(result_0, 0.07, ""); }

Çıktı sonucu amount'un değeri 0.69999999999999995559 olarak gösteriliyor, bu da kesin 0.7 değil. Bölme işleminin sonucu da beklenen 0.07 yerine hassas olmayan 0.06999999999999999 oldu.

Bu sorunu çözmek için sabit nokta sayıları kullanmayı düşünebilirsiniz. NEAR Protokolü'nde, 1 NEAR token'ı temsil etmek için genellikle 10^24 yoctoNEAR kullanılır. Değiştirilmiş test kodu:

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

Bu şekilde kesin hesaplama sonucu elde edilebilir: 0.7 NEAR / 10 = 0.07 NEAR.

2. Rust tam sayı hesaplamalarında hassasiyet sorunu

Tam sayı işlemleri, bazı senaryolarda kayan nokta işlemlerinin hassasiyet kaybı sorununu çözebilir, ancak tam sayı hesaplama sonuçları da tamamen doğru ve güvenilir değildir.

2.1 İşlem Sırası

Aynı aritmetik önceliğe sahip çarpma ve bölme işlemlerinin sırasının değiştirilmesi, hesaplama sonuçlarını doğrudan etkileyebilir ve tam sayı hesaplama doğruluğu sorunlarına yol açabilir. Örneğin:

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

}

Yürütme sonucu, result_0 ile result_1'in eşit olmadığını gösteriyor. Bunun nedeni, tam sayı bölmesinin, bölenin altındaki hassasiyeti atmasıdır. result_1'i hesaplarken, (a / b) önce hassasiyeti kaybedip 0'a dönüşüyor; oysa result_0'ı hesaplarken, a * c hesaplanarak hassasiyet kaybı önleniyor.

2.2 çok küçük bir büyüklük

Ondalık hesaplamalar söz konusu olduğunda, tam sayılı işlemler hassasiyet kaybına neden olabilir:

pas #[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");

println!("{}:{}", result_0, result_1);
assert_eq!(result_0, result_1, "");

}

Sonuçlar gösteriyor ki result_0=12, result_1=13, ancak beklenen değer 13.3333....

3. Sayısal Aktüeryalık için Rust akıllı sözleşmeleri nasıl yazılır

Hassasiyeti artırmak için aşağıdaki koruma önlemleri alınabilir:

3.1 İşlem sırasını ayarlama

Tam sayı çarpımının tam sayı bölümüne öncelik vermesini sağla.

3.2 Tam sayının büyüklüğünü artırın

Daha büyük bir ölçek kullanarak, daha büyük moleküller yaratın. Örneğin, 5.123 NEAR'ı göstermek için 5.123 * 10^10 = 51_230_000_000 ile sonraki hesaplamalara katılabilirsiniz.

3.3 Birikim işlemi hassasiyeti kaybı

Kaçınılmaz hassasiyet sorunları için, biriken hesaplama hassasiyet kaybını kaydedebilirsiniz. Örneğin:

pas const USER_NUM: u128 = 3;

u128 { let token_to_distribute = offset + amount; let per_user_share = token_to_distribute / USER_NUM; println!("per_user_share {}", per_user_share); let recorded_offset = token_to_distribute - per_user_share * USER_NUM; kaydedilen_offset }

#( fn record_offset_test)[test] { let mut offset: u128 = 0; for i in 1..7 { println!("Round {}", i); offset = distribute(to_yocto)"10"(, offset(; println!)"Offset {}\n", offset); } }

Bu yöntem, her dağıtımda kalan token'ları biriktirerek sonraki dağıtımda birlikte vermeyi sağlar ve nihayetinde yeterli dağıtım amacına ulaşır.

( 3.4 Rust Crate rust-decimal kütüphanesini kullanma

Bu kütüphane, doğru hassasiyet hesaplaması ve yuvarlama hatası olmayan ondalık finansal hesaplamalar için uygundur.

) 3.5 Yuvarlama mekanizmasını dikkate alma

Akıllı sözleşme tasarımında, yuvarlama sorunları genellikle "Ben kazanç sağlamak istiyorum, diğerleri benim kazancımı alamaz" ilkesine göre ele alınır. Duruma göre aşağıya veya yukarıya yuvarlama seçilir, nadiren en yakın tam sayıya yuvarlama yapılır.

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

View Original
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.
  • Reward
  • 8
  • Share
Comment
0/400
rugpull_survivorvip
· 07-14 15:34
Birçok insanı tuzağa düşürdü.
View OriginalReply0
WhaleWatchervip
· 07-14 07:46
Hassasiyet kontrolü çok önemlidir.
View OriginalReply0
consensus_failurevip
· 07-13 12:52
Sabit hassasiyetle daha güvenli
View OriginalReply0
Ser_Liquidatedvip
· 07-12 19:41
再出精度问题必Tasfiye Ol
View OriginalReply0
DecentralizeMevip
· 07-11 16:13
Sabit sayılarla değiştirelim.
View OriginalReply0
BoredWatchervip
· 07-11 15:58
Kod biraz karmaşık.
View OriginalReply0
BrokenDAOvip
· 07-11 15:53
Bilgi İşlem Gücü toplam aşımı sorun olur.
View OriginalReply0
MEVSandwichMakervip
· 07-11 15:51
Eski bir tuzak, etrafından dolaşmanızı öneririm.
View OriginalReply0
Trade Crypto Anywhere Anytime
qrCode
Scan to download Gate app
Community
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)