Дневник по развитию смарт-контрактов на Rust (7) Проблемы с точностью операций с плавающей запятой и целыми числами
В данной статье будет обсуждаться проблема точности операций с плавающей точкой и целыми числами в смарт-контрактах на Rust, а также то, как написать смарт-контракты для численных расчетов.
1. Проблема точности операций с плавающей запятой
Язык Rust изначально поддерживает операции с плавающей запятой, но у операций с плавающей запятой есть неизбежные проблемы с точностью вычислений. При написании смарт-контрактов не рекомендуется использовать операции с плавающей запятой, особенно при обработке коэффициентов или процентных ставок, касающихся важных экономических/финансовых решений.
В языке Rust числа с плавающей запятой используют стандарт IEEE 754 и представлены в виде научной нотации с основанием 2. Некоторые десятичные дроби (, такие как 0.7), не могут быть точно представлены с помощью чисел с плавающей запятой конечной длины, что приводит к явлению "округления".
Например, при распределении 0.7 токенов NEAR между 10 пользователями в блокчейне NEAR:
Результаты выполнения показывают, что значение amount не точно 0.7, а является приближенным значением 0.69999999999999995559. Результат деления также неточный, равен 0.06999999999999999 вместо ожидаемых 0.07.
Для решения этой проблемы можно рассмотреть использование фиксированной точки. В протоколе NEAR обычно используется обозначение 1 NEAR = 10^24 yoctoNEAR:
Результат выполнения показывает, что result_0 и result_1 не равны. Причина в том, что целочисленное деление отбрасывает точность, меньшую, чем делитель. При вычислении result_1, (a / b) сначала теряет точность и становится равным 0; в то время как при вычислении result_0, предварительное вычисление a * c позволяет избежать потери точности.
2.2 слишком маленький масштаб
Слишком малый порядок величины также может привести к проблемам с точностью:
#[test]
FN record_offset_test() {
let mut offset: u128 = 0;
для i в 1..7 {
offset = distribute(to_yocto("10"), offset);
}
}
Таким образом, токены, которые не были распределены, могут быть временно сохранены и выданы вместе при следующем распределении.
3.4 Использование Rust Crate библиотеки rust-decimal
Эта библиотека подходит для финансовых вычислений с дробными числами, требующими точности вычислений и не допускающими ошибок округления.
3.5 Учитывая механизм округления
При проектировании смарт-контрактов обычно используется принцип "Я хочу получить выгоду, другим не позволено стричь мои овцы". В зависимости от ситуации выбирается округление вниз или вверх, округление до ближайшего целого числа используется крайне редко.
!
Посмотреть Оригинал
На этой странице может содержаться сторонний контент, который предоставляется исключительно в информационных целях (не в качестве заявлений/гарантий) и не должен рассматриваться как поддержка взглядов компании Gate или как финансовый или профессиональный совет. Подробности смотрите в разделе «Отказ от ответственности» .
12 Лайков
Награда
12
8
Поделиться
комментарий
0/400
SandwichHunter
· 07-16 18:07
rust маленькая курочка снова лежит на земле
Посмотреть ОригиналОтветить0
WhaleStalker
· 07-16 17:00
Кодовые ошибки действительно убивают...
Посмотреть ОригиналОтветить0
GhostInTheChain
· 07-15 16:28
rust еще нужно заполнить дробью... не просто
Посмотреть ОригиналОтветить0
BoredWatcher
· 07-13 18:40
Библиотека rust может писать контракты?
Посмотреть ОригиналОтветить0
GasFeeNightmare
· 07-13 18:35
Точность вычислений беспокоит меня, как и мой Газ.
Посмотреть ОригиналОтветить0
EyeOfTheTokenStorm
· 07-13 18:34
Потеря точности напрямую влияет на соотношение прибыли и убытков, кто еще использует числа с плавающей запятой для количественного анализа? Даже азартные игроки, похоже, уже ушли в мошенничество.
Посмотреть ОригиналОтветить0
TokenEconomist
· 07-13 18:32
на самом деле, потеря точности = f(ордер_операций, масштабный_фактор) ... rust-decimal библиотека рулят
Проблемы точности числовых операций и оптимизационные решения в смарт-контрактах на Rust
Дневник по развитию смарт-контрактов на Rust (7) Проблемы с точностью операций с плавающей запятой и целыми числами
В данной статье будет обсуждаться проблема точности операций с плавающей точкой и целыми числами в смарт-контрактах на Rust, а также то, как написать смарт-контракты для численных расчетов.
1. Проблема точности операций с плавающей запятой
Язык Rust изначально поддерживает операции с плавающей запятой, но у операций с плавающей запятой есть неизбежные проблемы с точностью вычислений. При написании смарт-контрактов не рекомендуется использовать операции с плавающей запятой, особенно при обработке коэффициентов или процентных ставок, касающихся важных экономических/финансовых решений.
В языке Rust числа с плавающей запятой используют стандарт IEEE 754 и представлены в виде научной нотации с основанием 2. Некоторые десятичные дроби (, такие как 0.7), не могут быть точно представлены с помощью чисел с плавающей запятой конечной длины, что приводит к явлению "округления".
Например, при распределении 0.7 токенов NEAR между 10 пользователями в блокчейне NEAR:
ржавчина #[test] fn 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] fn precision_test_integer() { пусть 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 = сумма / делитель; 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] fn precision_test_div_before_mul() { пусть a: u128 = 1_0000; пусть b: u128 = 10_0000; пусть c: u128 = 20;
}
Результат выполнения показывает, что result_0 и result_1 не равны. Причина в том, что целочисленное деление отбрасывает точность, меньшую, чем делитель. При вычислении result_1, (a / b) сначала теряет точность и становится равным 0; в то время как при вычислении result_0, предварительное вычисление a * c позволяет избежать потери точности.
2.2 слишком маленький масштаб
Слишком малый порядок величины также может привести к проблемам с точностью:
ржавчина #[test] fn precision_test_decimals() { пусть a: u128 = 10; пусть b: u128 = 3; пусть c: u128 = 4; пусть десятичная: u128 = 100_0000;
}
Результаты показывают, что 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;
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; записанное_смещение }
#[test] FN record_offset_test() { let mut offset: u128 = 0; для i в 1..7 { offset = distribute(to_yocto("10"), offset); } }
Таким образом, токены, которые не были распределены, могут быть временно сохранены и выданы вместе при следующем распределении.
3.4 Использование Rust Crate библиотеки rust-decimal
Эта библиотека подходит для финансовых вычислений с дробными числами, требующими точности вычислений и не допускающими ошибок округления.
3.5 Учитывая механизм округления
При проектировании смарт-контрактов обычно используется принцип "Я хочу получить выгоду, другим не позволено стричь мои овцы". В зависимости от ситуации выбирается округление вниз или вверх, округление до ближайшего целого числа используется крайне редко.
!