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

Rust العقود الذكية养成日记(7):数值精算

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

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

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

في اختبار توزيع 0.7 من رموز NEAR على عشرة مستخدمين على سلسلة NEAR العامة، كانت نتائج العمليات العائمة غير دقيقة:

صدأ دع المبلغ: F64 = 0.7 ؛
دع المقسوم عليه: F64 = 10.0 ؛ دع result_0 = الكمية / القاسم ؛

قيمة amount هي 0.69999999999999995559، وقيمة result_0 هي 0.06999999999999999، وليس 0.07 كما هو متوقع.

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

صدأ دع N: u128 = 1_000_000_000_000_000_000_000_000_000 ؛ المبلغ اليدخ: U128 = 700_000_000_000_000_000_000_000 ؛ دع المقسوم: U128 = 10 ؛ دع result_0 = الكمية / القاسم ؛

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

!

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

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

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

صدأ دع أ: U128 = 1_0000 ؛ دع ب: U128 = 10_0000 ؛ دع C: U128 = 20 ؛

result_0 = أ * ج / ب دع result_0 = a.checked_mul(c).expect( "ERR_MUL").checked_ div(b).expect( "ERR_DIV" );

result_1 = أ / ب * ج
دع result_1 = a.checked_div(b).expect("ERR_DIV").checked_ mul(c).expect( "ERR_MUL" );

نتيجة_0 ونتيجة_1 مختلفة في الحساب، لأن الدقة الأقل من القاسم ستُهمل في قسمة الأعداد الصحيحة.

2.2 حجم صغير جدًا

عند التعامل مع القيم الصغيرة، قد تؤدي العمليات الصحيحة إلى فقدان الدقة:

صدأ دع أ: u128 = 10 ؛ دع ب: u128 = 3 ؛ دع C: U128 = 4 ؛ دع الرقم العشري: U128 = 100_0000 ؛

result_0 = (a / b) * ج دع result_0 = a.checked_div(b).expect("ERR_DIV").checked_ mul(c).expect( "ERR_MUL" );

result_1 = (a * عشري / b) * ج / عشري ؛
دع 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 و result_1 مختلفة، و result_1 أقرب إلى القيمة المتوقعة الفعلية.

!

3. كيفية كتابة العقود الذكية Rust لتقييم الأرقام

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

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

3.2 زيادة عدد الأعداد الصحيحة

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

3.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 }

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

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

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

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

!

TOKEN3.79%
NUM1.15%
شاهد النسخة الأصلية
قد تحتوي هذه الصفحة على محتوى من جهات خارجية، يتم تقديمه لأغراض إعلامية فقط (وليس كإقرارات/ضمانات)، ولا ينبغي اعتباره موافقة على آرائه من قبل Gate، ولا بمثابة نصيحة مالية أو مهنية. انظر إلى إخلاء المسؤولية للحصول على التفاصيل.
  • أعجبني
  • 3
  • مشاركة
تعليق
0/400
BearMarketBuildervip
· 08-05 07:58
هذه الحفرة في الأرقام العشرية عميقة مثل البحر
شاهد النسخة الأصليةرد0
SelfSovereignStevevip
· 08-05 07:53
الأعداد العشرية مزعجة للغاية، العقود الذكية ستنفجر، لا أجرؤ على استخدامها على الإطلاق.
شاهد النسخة الأصليةرد0
DegenGamblervip
· 08-05 07:49
إخواني الذين يلعبون Rust انتبهوا، فخ الدقة ليس صغيرًا
شاهد النسخة الأصليةرد0
  • تثبيت