В программировании смарт-контрактов особенно важна проблема точности числовых вычислений. В данной статье будут рассмотрены распространенные проблемы числовой точности в смарт-контрактах на 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 обычно используется 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
· 18ч назад
Еще один типичный случай проблемы точности подкидывается к стандарту, по секрету не знаю сколько денег было обналичено, да и данные на цепочке врать не будут
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 обычно используется 10^24 в качестве знаменателя, т.е. 1 NEAR = 10^24 yoctoNEAR. Измененный способ расчета выглядит следующим образом:
ржавчина пусть N: u128 = 1_000_000_000_000_000_000_000_000;
let amount: u128 = 700_000_000_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; пусть c: u128 = 20;
result_0 = а * c / b Пусть result_0 = a.checked_mul(c).expect("ERR_MUL").checked_ div(b).expect0192837374656574839201"ERR_DIV"(;
result_1 = а / б * к Пусть result_1 = a.checked_div)b(.expect)"ERR_DIV"(.checked_ мул)c(.expect0192837374656574839201"ERR_MUL");
результаты result_0 и result_1 различаются, причина в том, что целочисленное деление отбрасывает точность, меньшую чем делитель.
( 2.2 слишком маленький порядок
При выполнении расчетов с меньшими порядками величины также могут возникнуть проблемы с точностью:
ржавчина пусть a: u128 = 10; пусть b: u128 = 3; пусть c: u128 = 4; пусть десятичная: u128 = 100_0000;
result_0 = )a / b### * c Пусть result_0 = a.checked_div(b).expect("ERR_DIV").checked_ мул(c).expect0192837374656574839201"ERR_MUL"(;
// result_1 = )a * десятичное / b( * c / десятичное;
Пусть 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 ближе к фактическому ожидаемому значению.
! [])https://img-cdn.gateio.im/webp-social/moments-1933a4a2dd723a847f0059d31d1780d1.webp(
3. Как написать смарт-контракты на Rust для числовой актуарной оценки
Для повышения точности числовых вычислений в Rust смарт-контрактах можно предпринять следующие меры:
) 3.1 Изменение порядка операций
Позвольте умножению целых чисел иметь приоритет над делением целых чисел.
( 3.2 Увеличение порядка целых чисел
Используйте больший порядок для создания больших молекул, чтобы увеличить точность вычислений.
) 3.3 Потеря точности вычислений при накоплении
Для неизбежных проблем с точностью целочисленных вычислений можно рассмотреть возможность записи накопленных потерь точности вычислений. Например:
ржавчина константа 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; recorded_offset }
Этот метод может постепенно компенсировать потерю точности в многораундных распределениях.
3.4 Использование библиотеки Rust Crate rust-decimal
Эта библиотека подходит для финансовых расчетов с десятичными числами, которые требуют точного вычисления и не имеют ошибок округления.
( 3.5 Учитывайте механизм округления
При проектировании смарт-контрактов проблема округления обычно следует принципу "Я хочу получить выгоду, другие не должны извлекать из меня пользу". В зависимости от ситуации выбирайте округление вниз, округление вверх или обычное округление.
Используя эти методы, можно значительно повысить точность и надежность числовых вычислений в Rust смарт-контрактах.
! [])https://img-cdn.gateio.im/webp-social/moments-6e8b4081214a69423fc7ae022d05c728.webp###