Язык Rust изначально поддерживает операции с плавающей точкой, но операции с плавающей точкой сталкиваются с неизбежными проблемами точности вычислений. При написании смарт-контрактов не рекомендуется использовать операции с плавающей точкой, особенно при обработке коэффициентов или процентных ставок, связанных с важными экономическими/финансовыми решениями.
Двойной точности тип с плавающей запятой f64 в языке Rust соответствует стандарту IEEE 754 и используется научная нотация с основанием 2. Некоторые десятичные дроби, такие как 0.7, не могут быть точно представлены конечной длиной числа с плавающей запятой, что приводит к явлению "округления".
В тестировании распределения 0.7 токенов NEAR десяти пользователям на блокчейне NEAR результат вычислений с плавающей точкой не точен:
Таким образом, можно получить точный результат вычисления: 0.7 NEAR / 10 = 0.07 NEAR.
!
2. Проблема точности вычислений с целыми числами в Rust
2.1 Порядок операций
При одинаковом уровне приоритета арифметики, изменение порядка выполнения умножения и деления может непосредственно влиять на результат вычислений. Например:
3.4 Использование библиотеки Rust Crate rust-decimal
Библиотека подходит для финансовых расчетов с десятичными числами, требующими точных вычислений и отсутствия ошибок округления.
( 3.5 Учитывайте механизм округления
В дизайне смарт-контрактов проблема округления обычно решается по принципу "Я хочу получить выгоду, другие не должны меня обманывать". В зависимости от ситуации выбирается округление вниз, округление вверх или округление до ближайшего целого.
На этой странице может содержаться сторонний контент, который предоставляется исключительно в информационных целях (не в качестве заявлений/гарантий) и не должен рассматриваться как поддержка взглядов компании Gate или как финансовый или профессиональный совет. Подробности смотрите в разделе «Отказ от ответственности» .
7 Лайков
Награда
7
3
Поделиться
комментарий
0/400
BearMarketBuilder
· 08-05 07:58
Эта яма с плавающей точкой просто глубока, как море.
Посмотреть ОригиналОтветить0
SelfSovereignSteve
· 08-05 07:53
Число с плавающей запятой слишком проблемное, смарт-контракты обязательно провалятся, совершенно не осмеливаюсь использовать.
Посмотреть ОригиналОтветить0
DegenGambler
· 08-05 07:49
Игроки Rust, обратите внимание, эта проблема с точностью не маленькая.
Разработка смарт-контрактов на 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 Protocol обычно используется представление 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 смарт-контракты для числовой актуарной оценки
) 3.1 Изменение порядка операций
Установите приоритет умножения целых чисел над делением целых чисел.
( 3.2 Увеличение порядков целых чисел
Используйте больший порядок, чтобы создать большие молекулы. Например, представьте 5.123 NEAR как 51_230_000_000 yoctoNEAR.
) 3.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 Учитывайте механизм округления
В дизайне смарт-контрактов проблема округления обычно решается по принципу "Я хочу получить выгоду, другие не должны меня обманывать". В зависимости от ситуации выбирается округление вниз, округление вверх или округление до ближайшего целого.
! [])https://img-cdn.gateio.im/webp-social/moments-6e8b4081214a69423fc7ae022d05c728.webp###