مشاكل دقة العمليات العددية في العقود الذكية بلغة Rust وخطط التحسين

robot
إنشاء الملخص قيد التقدم

يوميات تطوير العقود الذكية بلغة Rust (7) مشكلة دقة العمليات على الأعداد العشرية والعدد الصحيح

ستتناول هذه المقالة مشكلة دقة عمليات الأعداد العشرية والأعداد الصحيحة في العقود الذكية بلغة Rust، وكيفية كتابة العقود الذكية الخاصة بالتقييم العددي.

1. مشكلة دقة العمليات العشرية

تدعم لغة Rust العمليات الحسابية العائمة بشكل أصلي، ولكن توجد مشاكل في دقة الحساب التي لا يمكن تجنبها عند إجراء العمليات العائمة. عند كتابة العقود الذكية، لا يُنصح باستخدام العمليات العائمة، خاصة عند التعامل مع النسب أو معدلات الفائدة المتعلقة بالقرارات الاقتصادية/المالية الهامة.

تستخدم أرقام الفاصلة العائمة في لغة Rust معيار IEEE 754، وتمثل بصيغة العد العلمي بأساس 2. بعض الأعداد العشرية مثل ( مثل 0.7) لا يمكن تمثيلها بدقة باستخدام أرقام فاصلة عائمة ذات طول محدود، مما يؤدي إلى ظاهرة "الجولة".

على سبيل المثال، عند توزيع 0.7 من رموز NEAR على 10 مستخدمين على سلسلة NEAR العامة:

صدأ #[test] الجبهة precision_test_float() { دع المبلغ: F64 = 0.7 ؛
دع المقسوم عليه: F64 = 10.0 ؛
دع result_0 = الكمية / القاسم ؛
assert_eq!(result_0 ، 0.07 ، "") ؛ }

تظهر نتائج التنفيذ أن قيمة amount ليست بالضبط 0.7، بل هي قيمة تقريبية 0.69999999999999995559. كما أن نتائج عملية القسمة ليست دقيقة، حيث إنها 0.06999999999999999 بدلاً من 0.07 المتوقعة.

لحل هذه المشكلة، يمكن النظر في استخدام الأعداد الثابتة. في بروتوكول NEAR، عادةً ما يتم استخدام طريقة التعبير 1 NEAR = 10^24 yoctoNEAR:

صدأ #[test] الجبهة الوطنية precision_test_integer() { دع N: u128 = 1_000_000_000_000_000_000_000_000_000 ؛
المبلغ اليدخ: U128 = 700_000_000_000_000_000_000_000 ؛ دع المقسوم: U128 = 10 ؛
دع النتيجة_0 = المبلغ / القاسم; assert_eq!(result_0, 70_000_000_000_000_000_000_000_000, ""); }

بهذه الطريقة يمكن الحصول على نتيجة حساب القيمة: 0.7 NEAR / 10 = 0.07 NEAR.

!

2. مشكلة دقة حسابات الأعداد الصحيحة في Rust

2.1 ترتيب العمليات

إن تغيير ترتيب الضرب والقسمة ذات الأولوية الحسابية نفسها قد يؤثر بشكل مباشر على نتيجة الحساب:

صدأ #[test] الجبهة precision_test_div_before_mul() { دع أ: U128 = 1_0000 ؛ دع ب: U128 = 10_0000 ؛ دع C: U128 = 20 ؛

دع result_0 = a.checked_mul(c).expect("ERR_MUL")
                .checked_div(b).expect("ERR_DIV");

دع result_1 = a.checked_div(b).expect("ERR_DIV")
                .checked_mul(c).expect("ERR_MUL");

assert_eq!(result_0,result_1,"");

}

نتيجة التنفيذ تظهر أن result_0 و result_1 غير متساويتين. السبب هو أن القسمة الصحيحة تتجاهل الدقة الأقل من المقام. عند حساب result_1، (a / b) ستفقد الدقة أولاً وتتحول إلى 0; بينما عند حساب result_0، يتم حساب a * c أولاً مما يمنع فقدان الدقة.

2.2 كمية صغيرة جداً

يمكن أن يؤدي الحجم الصغير جداً أيضًا إلى مشاكل في الدقة:

صدأ #[test] الجبهة precision_test_decimals() { دع أ: u128 = 10 ؛ دع ب: u128 = 3 ؛ دع C: U128 = 4 ؛ دع الرقم العشري: U128 = 100_0000 ؛

دع result_0 = a.checked_div(b).expect("ERR_DIV")
                .checked_mul(c).expect("ERR_MUL");

دع 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");

assert_eq!(result_0 ، result_1 ، "") ؛

}

تظهر النتائج result_0=12، result_1=13، والنتيجة الأخيرة أقرب إلى القيمة المتوقعة 13.3333.

!

3. كيفية كتابة العقود الذكية بلغة Rust الخاصة بالتقييم العددي

لزيادة الدقة، يمكن اتخاذ التدابير الوقائية التالية:

3.1 تعديل ترتيب العمليات

اجعل ضرب الأعداد الصحيحة له أولوية على قسمة الأعداد الصحيحة.

3.2 زيادة مرتبة الأعداد الصحيحة

استخدم مقاييس أكبر لإنشاء جزيئات أكبر. على سبيل المثال، يتم تمثيل 5.123 NEAR كـ 5.123 * 10^10 = 51_230_000_000.

3.3 خسارة دقة العمليات التراكمية

سجل فقدان دقة العمليات المتراكمة:

صدأ كونست USER_NUM: U128 = 3 ؛

الجبهة distribute(amount: U128 ، الإزاحة: u128) -> U128 { دع token_to_distribute = الإزاحة + المبلغ ؛ دع per_user_share = token_to_distribute / USER_NUM ؛ دع recorded_offset = token_to_distribute - per_user_share * USER_NUM ؛ recorded_offset }

#[test] الجبهة الوطنية record_offset_test() { دع إزاحة MUT: U128 = 0 ؛ من أجل i في 1..7 { الإزاحة = distribute(to_yocto( "10" ) ، offset) ؛ } }

يمكن أن يؤدي هذا إلى تخزين الرموز المميزة غير الموزعة، ليتم توزيعها معًا في المرة القادمة.

3.4 استخدام مكتبة Rust Crate rust-decimal

تتناسب هذه المكتبة مع الحسابات المالية العشرية التي تتطلب دقة حساب فعالة ولا تحتوي على أخطاء التقريب.

3.5 النظر في آلية التقريب

العقود الذكية تصميمها يعتمد عادةً على مبدأ "أريد أن أستفيد، ولا ينبغي للآخرين استغلالي". يتم اختيار التقريب للأسفل أو للأعلى حسب الحالة، ونادرًا ما يتم استخدام التقريب إلى أقرب عدد.

!

شاهد النسخة الأصلية
قد تحتوي هذه الصفحة على محتوى من جهات خارجية، يتم تقديمه لأغراض إعلامية فقط (وليس كإقرارات/ضمانات)، ولا ينبغي اعتباره موافقة على آرائه من قبل Gate، ولا بمثابة نصيحة مالية أو مهنية. انظر إلى إخلاء المسؤولية للحصول على التفاصيل.
  • أعجبني
  • 8
  • مشاركة
تعليق
0/400
SandwichHuntervip
· 07-16 18:07
الروست الصغير مرة أخرى مستلقي على الأرض
شاهد النسخة الأصليةرد0
WhaleStalkervip
· 07-16 17:00
الأخطاء البرمجية قاتلة حقاً...
شاهد النسخة الأصليةرد0
GhostInTheChainvip
· 07-15 16:28
يجب أيضًا ملء الأرقام العشرية لـ rust... ليس بالأمر السهل
شاهد النسخة الأصليةرد0
BoredWatchervip
· 07-13 18:40
هل يمكن لمكتبة Rust كتابة عقود؟
شاهد النسخة الأصليةرد0
GasFeeNightmarevip
· 07-13 18:35
دقة العمليات مزعجة مثل غاز الرسوم الخاصة بي...
شاهد النسخة الأصليةرد0
EyeOfTheTokenStormvip
· 07-13 18:34
معدل فقدان الدقة يؤثر مباشرة على نسبة الأرباح والخسائر، من لا يزال يستخدم الأرقام العشرية في التداول؟ هل هربت حتى المقامرة؟
شاهد النسخة الأصليةرد0
TokenEconomistvip
· 07-13 18:32
في الواقع، خسارة الدقة = f(طلب_order_of_ops، scale_factor) ... مكتبة rust-decimal للأفضل
شاهد النسخة الأصليةرد0
just_another_walletvip
· 07-13 18:25
الأرقام العشرية مزعجة جداً...
شاهد النسخة الأصليةرد0
  • تثبيت