На відміну від поширеної мови програмування смартконтрактів Solidity, мова Rust нативно підтримує операції з плаваючою крапкою. Однак операції з плаваючою крапкою мають невідворотні проблеми з обчислювальною точністю. Тому при написанні смартконтрактів не рекомендується використовувати операції з плаваючою крапкою, особливо при обробці співвідношень або відсоткових ставок, що стосуються важливих економічних або фінансових рішень.
На сьогоднішній день основні мови програмування, що представляють дійсні числа з плаваючою комою, переважно дотримуються стандарту IEEE 754, мова Rust не є винятком. Тип з подвійною точністю f64 зберігається в комп'ютері у вигляді двійкових даних.
Числа з плаваючою комою використовують науковий запис з основою 2 для вираження. Наприклад, число 0.1101 у скінченній бітовій формі може представляти десяткове число 0.8125. Проте для десяткового числа 0.7 під час перетворення в число з плаваючою комою виникає безкінечне циклічне двійкове представлення, яке не можна точно відобразити за допомогою скінченної довжини числа з плаваючою комою, що призводить до явища "округлення".
Припустимо, потрібно розподілити 0.7 токенів між десятьма користувачами, кількість токенів, яку отримає кожен користувач, буде обчислена та збережена в змінній result_0. Після виконання відповідних тестових випадків ми можемо помітити, що значення amount не точно відображає 0.7, а є вкрай близьким значенням 0.69999999999999995559. Додатково, для одиничної операції ділення amount/divisor, результат також стане неточним 0.06999999999999999, а не очікуваним 0.07. З цього видно невизначеність обчислень з плаваючою комою.
Для цього нам потрібно розглянути використання інших типів числових представлень у смартконтрактах, таких як фіксована точка. У процесі написання смартконтрактів зазвичай використовується дроб, що має фіксований знаменник для представлення певного значення, наприклад, дробу x/N, де N є константою, а x може змінюватися.
В деяких публічних блокчейнах N часто дорівнює 10^24, тобто 10^24 найменших одиниць еквівалентно 1 основній одиниці токена. На основі цього ми можемо змінити обчислення з плаваючою комою на цілі числа, щоб отримати більш точні результати.
!
2. Проблема точності обчислень цілих чисел у Rust
Використання цілочисельних обчислень може вирішити проблему втрати точності обчислень з плаваючою комою в деяких сценаріях. Але це не означає, що результати цілочисельних обчислень абсолютно точні та надійні. Частина причин, що впливають на точність цілочисельних обчислень, включає:
2.1 порядок виконання операцій
У однакових арифметичних пріоритетах множення та ділення зміна їх послідовності може безпосередньо вплинути на результат обчислень, що призводить до проблеми точності обчислень цілих чисел. Щодо цілочисельного ділення, точність, що менша за дільник, буде відкинута. Тому в деяких обчислювальних процесах, якщо спочатку виконати операцію ділення, це може призвести до втрати точності.
2.2 занадто малий порядок величини
Коли значення, що береться до уваги, занадто маленьке, цілісні обчислення також можуть призвести до проблем з точністю. Наприклад, у деяких випадках пряме виконання цілочисельних обчислень і виконання обчислень після введення більшого порядку величини можуть дати різні результати.
!
3. Як написати смартконтракти на Rust для числової актуарії
Щоб забезпечити точність обчислень у смартконтрактах, можна вжити такі заходи захисту:
3.1 Зміна порядку виконання операцій
Старайтесь, щоб множення цілих чисел відбувалося перед діленням цілих чисел.
3.2 збільшити порядок цілого числа
Використовуйте більший порядок для представлення значень, створюючи більші чисельники для участі в обчисленнях, щоб підвищити точність.
3.3 накопичення втрати точності обчислень
Щодо неминучих проблем з точністю обчислень цілих чисел, можна розглянути можливість реєстрації накопичених втрат точності обчислень. У подальших розрахунках ці втрати слід враховувати для досягнення більш справедливого розподілу результатів.
3.4 Використання бібліотеки Rust Crate rust-decimal
Ця бібліотека підходить для фінансових обчислень з десятковими числами, які потребують високої точності та не мають помилок округлення.
3.5 Розгляньте механізм округлення
При проектуванні смартконтрактів проблеми округлення зазвичай дотримуються принципу "на користь собі, на шкоду іншим". Вибирайте округлення вниз, округлення вгору або інші відповідні способи округлення відповідно до конкретних обставин.
Завдяки цим заходам можна досягти більш точної числової обробки в Rust смартконтрактах, уникнувши помилок або несправедливих результатів через проблеми з точністю.
!
Переглянути оригінал
Ця сторінка може містити контент третіх осіб, який надається виключно в інформаційних цілях (не в якості запевнень/гарантій) і не повинен розглядатися як схвалення його поглядів компанією Gate, а також як фінансова або професійна консультація. Див. Застереження для отримання детальної інформації.
13 лайків
Нагородити
13
8
Репост
Поділіться
Прокоментувати
0/400
SeasonedInvestor
· 07-19 12:17
Точність дійсно підводить.
Переглянути оригіналвідповісти на0
RugPullProphet
· 07-18 09:14
Контроль точності має бути на рівні
Переглянути оригіналвідповісти на0
GasOptimizer
· 07-16 19:00
Точність — це життя
Переглянути оригіналвідповісти на0
TestnetScholar
· 07-16 18:56
Використання цілочисельних розрахунків є більш надійним
Техніки точного обчислення значень у смартконтрактах Rust: уникнення пасток з плаваючою комою
Rust смартконтракти养成日记(7)数值精算
1. Проблема точності обчислень з плаваючою комою
На відміну від поширеної мови програмування смартконтрактів Solidity, мова Rust нативно підтримує операції з плаваючою крапкою. Однак операції з плаваючою крапкою мають невідворотні проблеми з обчислювальною точністю. Тому при написанні смартконтрактів не рекомендується використовувати операції з плаваючою крапкою, особливо при обробці співвідношень або відсоткових ставок, що стосуються важливих економічних або фінансових рішень.
На сьогоднішній день основні мови програмування, що представляють дійсні числа з плаваючою комою, переважно дотримуються стандарту IEEE 754, мова Rust не є винятком. Тип з подвійною точністю f64 зберігається в комп'ютері у вигляді двійкових даних.
Числа з плаваючою комою використовують науковий запис з основою 2 для вираження. Наприклад, число 0.1101 у скінченній бітовій формі може представляти десяткове число 0.8125. Проте для десяткового числа 0.7 під час перетворення в число з плаваючою комою виникає безкінечне циклічне двійкове представлення, яке не можна точно відобразити за допомогою скінченної довжини числа з плаваючою комою, що призводить до явища "округлення".
Припустимо, потрібно розподілити 0.7 токенів між десятьма користувачами, кількість токенів, яку отримає кожен користувач, буде обчислена та збережена в змінній result_0. Після виконання відповідних тестових випадків ми можемо помітити, що значення amount не точно відображає 0.7, а є вкрай близьким значенням 0.69999999999999995559. Додатково, для одиничної операції ділення amount/divisor, результат також стане неточним 0.06999999999999999, а не очікуваним 0.07. З цього видно невизначеність обчислень з плаваючою комою.
Для цього нам потрібно розглянути використання інших типів числових представлень у смартконтрактах, таких як фіксована точка. У процесі написання смартконтрактів зазвичай використовується дроб, що має фіксований знаменник для представлення певного значення, наприклад, дробу x/N, де N є константою, а x може змінюватися.
В деяких публічних блокчейнах N часто дорівнює 10^24, тобто 10^24 найменших одиниць еквівалентно 1 основній одиниці токена. На основі цього ми можемо змінити обчислення з плаваючою комою на цілі числа, щоб отримати більш точні результати.
!
2. Проблема точності обчислень цілих чисел у Rust
Використання цілочисельних обчислень може вирішити проблему втрати точності обчислень з плаваючою комою в деяких сценаріях. Але це не означає, що результати цілочисельних обчислень абсолютно точні та надійні. Частина причин, що впливають на точність цілочисельних обчислень, включає:
2.1 порядок виконання операцій
У однакових арифметичних пріоритетах множення та ділення зміна їх послідовності може безпосередньо вплинути на результат обчислень, що призводить до проблеми точності обчислень цілих чисел. Щодо цілочисельного ділення, точність, що менша за дільник, буде відкинута. Тому в деяких обчислювальних процесах, якщо спочатку виконати операцію ділення, це може призвести до втрати точності.
2.2 занадто малий порядок величини
Коли значення, що береться до уваги, занадто маленьке, цілісні обчислення також можуть призвести до проблем з точністю. Наприклад, у деяких випадках пряме виконання цілочисельних обчислень і виконання обчислень після введення більшого порядку величини можуть дати різні результати.
!
3. Як написати смартконтракти на Rust для числової актуарії
Щоб забезпечити точність обчислень у смартконтрактах, можна вжити такі заходи захисту:
3.1 Зміна порядку виконання операцій
Старайтесь, щоб множення цілих чисел відбувалося перед діленням цілих чисел.
3.2 збільшити порядок цілого числа
Використовуйте більший порядок для представлення значень, створюючи більші чисельники для участі в обчисленнях, щоб підвищити точність.
3.3 накопичення втрати точності обчислень
Щодо неминучих проблем з точністю обчислень цілих чисел, можна розглянути можливість реєстрації накопичених втрат точності обчислень. У подальших розрахунках ці втрати слід враховувати для досягнення більш справедливого розподілу результатів.
3.4 Використання бібліотеки Rust Crate rust-decimal
Ця бібліотека підходить для фінансових обчислень з десятковими числами, які потребують високої точності та не мають помилок округлення.
3.5 Розгляньте механізм округлення
При проектуванні смартконтрактів проблеми округлення зазвичай дотримуються принципу "на користь собі, на шкоду іншим". Вибирайте округлення вниз, округлення вгору або інші відповідні способи округлення відповідно до конкретних обставин.
Завдяки цим заходам можна досягти більш точної числової обробки в Rust смартконтрактах, уникнувши помилок або несправедливих результатів через проблеми з точністю.
!