У програмуванні смартконтрактів питання точності числових обчислень є особливо важливими. У цій статті буде розглянуто поширені проблеми числових обчислень у смартконтрактах Rust та їхні рішення.
1. Проблема точності обчислень з плаваючою комою
Мова Rust надає рідну підтримку операцій з плаваючою комою, але в операціях з плаваючою комою існує невідворотна проблема обчислювальної точності. Не рекомендується використовувати операції з плаваючою комою при обробці коефіцієнтів або відсоткових ставок, що стосуються важливих економічних/фінансових рішень.
Тип даних з подвійною точністю f64 у мові Rust відповідає стандарту IEEE 754 і використовує наукову нотацію з основою 2. Деякі дроби (, такі як 0.7), не можуть бути точно представлені з обмеженою кількістю бітів, що призводить до явища "округлення".
Наприклад, при розподілі 0.7 NEAR токенів 10 користувачам на блокчейні NEAR:
фактичне значення amount становить 0.69999999999999995559, результат result_0 становить 0.06999999999999999, а не очікувані 0.07.
Щоб вирішити цю проблему, можна розглянути використання фіксованої точності. У NEAR Protocol зазвичай використовується 10^24 як знаменник, тобто 1 NEAR = 10^24 yoctoNEAR. Змінений спосіб обчислення виглядає так:
Так можна отримати точний обчислений результат: 0.7 NEAR / 10 = 0.07 NEAR.
!
2. Проблема точності обчислень з цілими числами в Rust
Використання цілочисельних обчислень, хоча і може вирішити проблеми з точністю плаваючої коми в деяких сценаріях, все ще має деякі фактори, які впливають на точність обчислень.
2.1 Порядок виконання операцій
Однаковий пріоритет арифметичних операцій множення та ділення, зміна їх порядку може безпосередньо вплинути на результат обчислень. Наприклад:
Цей метод може поступово компенсувати втрату точності у багатократному розподілі.
3.4 Використання бібліотеки Rust Crate rust-decimal
Ця бібліотека підходить для фінансових обчислень з десятковими числами, які потребують точного обчислення та не мають округлювальних помилок.
( 3.5 Розгляньте механізм округлення
При проектуванні смартконтрактів, проблема округлення зазвичай дотримується принципу "Я хочу виграти, інші не повинні мене обманювати". Вибирайте округлення вниз, округлення вгору або округлення до найближчого цілого залежно від ситуації.
Завдяки використанню цих методів можна суттєво підвищити точність і надійність числових обчислень у Rust смартконтрактах.
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 лайків
Нагородити
7
3
Поділіться
Прокоментувати
0/400
MaticHoleFiller
· 17год тому
Цілий день застрягли в проблемах точності, втративши всі зусилля.
Переглянути оригіналвідповісти на0
StablecoinAnxiety
· 17год тому
Трохи важко, коли потрібно і алгоритм, і фінанси~
Переглянути оригіналвідповісти на0
GhostAddressMiner
· 17год тому
Ще один типовий випадок, коли проблема з точністю перекладається на стандарти, а насправді невідомо, скільки коштів було виведено, у блокчейні дані не будуть брехати.
Rust смартконтракти числове оцінювання: посібник по уникненню пасток та найкращі практики
Обчислення чисел у смартконтрактах Rust
У програмуванні смартконтрактів питання точності числових обчислень є особливо важливими. У цій статті буде розглянуто поширені проблеми числових обчислень у смартконтрактах Rust та їхні рішення.
1. Проблема точності обчислень з плаваючою комою
Мова Rust надає рідну підтримку операцій з плаваючою комою, але в операціях з плаваючою комою існує невідворотна проблема обчислювальної точності. Не рекомендується використовувати операції з плаваючою комою при обробці коефіцієнтів або відсоткових ставок, що стосуються важливих економічних/фінансових рішень.
Тип даних з подвійною точністю f64 у мові Rust відповідає стандарту IEEE 754 і використовує наукову нотацію з основою 2. Деякі дроби (, такі як 0.7), не можуть бути точно представлені з обмеженою кількістю бітів, що призводить до явища "округлення".
Наприклад, при розподілі 0.7 NEAR токенів 10 користувачам на блокчейні NEAR:
іржа Нехай кількість: f64 = 0,7;
Нехай дільник: f64 = 10,0;
нехай result_0 = сума / дільник;
фактичне значення amount становить 0.69999999999999995559, результат result_0 становить 0.06999999999999999, а не очікувані 0.07.
Щоб вирішити цю проблему, можна розглянути використання фіксованої точності. У NEAR Protocol зазвичай використовується 10^24 як знаменник, тобто 1 NEAR = 10^24 yoctoNEAR. Змінений спосіб обчислення виглядає так:
іржа нехай N: u128 = 1_000_000_000_000_000_000_000;
Нехай кількість: U128 = 700_000_000_000_000_000; Нехай дільник: u128 = 10;
нехай result_0 = сума / дільник;
Так можна отримати точний обчислений результат: 0.7 NEAR / 10 = 0.07 NEAR.
!
2. Проблема точності обчислень з цілими числами в Rust
Використання цілочисельних обчислень, хоча і може вирішити проблеми з точністю плаваючої коми в деяких сценаріях, все ще має деякі фактори, які впливають на точність обчислень.
2.1 Порядок виконання операцій
Однаковий пріоритет арифметичних операцій множення та ділення, зміна їх порядку може безпосередньо вплинути на результат обчислень. Наприклад:
іржа Нехай a: u128 = 1_0000; нехай b: u128 = 10_0000; Нехай С: U128 = 20;
result_0 = а * с / б let result_0 = a.checked_mul(c).expect("ERR_MUL").checked_ div019283746574839201b(.expect)"ERR_DIV"(;
result_1 = а / б * с нехай result_1 = a.checked_div)b(.expect)"ERR_DIV"(.checked_ MUL019283746574839201c).expect("ERR_MUL");
результати result_0 і result_1 різні, причина в тому, що цілочисельне ділення відкидає точність, меншу за дільник.
( 2.2 занадто малий масштаб
Коли йдеться про обчислення з меншими порядками величини, це також може призвести до проблем з точністю:
ржавчина Нехай А: U128 = 10; нехай b: u128 = 3; Нехай c: u128 = 4; Нехай десятковий дріб: u128 = 100_0000;
result_0 = )a / b### * с let result_0 = a.checked_div(b).expect("ERR_DIV").checked_ MUL019283746574839201c(.expect)"ERR_MUL"(;
// result_1 = )a * десятковий / b( * c / десятковий; let result_1 = a.checked_mul)decimal(.expect)"ERR_MUL"( .checked_div)b(.expect)"ERR_DIV"( .checked_mul)c(.expect)"ERR_MUL"( .перевірено_div)десятковий(.очікувати)"ERR_DIV"(;
результати обчислень result_0 та result_1 різні, і result_1 ближчий до фактичного очікуваного значення.
! [])https://img-cdn.gateio.im/webp-social/moments-1933a4a2dd723a847f0059d31d1780d1.webp(
3. Як написати Rust смартконтракти для числового актуаріального обліку
Щоб підвищити точність числових обчислень у смартконтрактах Rust, можна вжити такі заходи:
) 3.1 зміна порядку виконання операцій
Нехай множення цілих чисел має пріоритет над діленням цілих чисел.
( 3.2 збільшити порядок цілого числа
Використовуйте більші масштаби для створення більших молекул, підвищуючи точність обчислень.
) 3.3 Втрата точності обчислень
Для невідворотних проблем точності обчислень з цілими числами можна розглянути можливість фіксації накопичених втрат точності обчислень. Наприклад:
іржа const USER_NUM: u128 = 3;
FN 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; записаний_зсув }
Цей метод може поступово компенсувати втрату точності у багатократному розподілі.
3.4 Використання бібліотеки Rust Crate rust-decimal
Ця бібліотека підходить для фінансових обчислень з десятковими числами, які потребують точного обчислення та не мають округлювальних помилок.
( 3.5 Розгляньте механізм округлення
При проектуванні смартконтрактів, проблема округлення зазвичай дотримується принципу "Я хочу виграти, інші не повинні мене обманювати". Вибирайте округлення вниз, округлення вгору або округлення до найближчого цілого залежно від ситуації.
Завдяки використанню цих методів можна суттєво підвищити точність і надійність числових обчислень у Rust смартконтрактах.
! [])https://img-cdn.gateio.im/webp-social/moments-6e8b4081214a69423fc7ae022d05c728.webp###