В отличие от распространённого языка программирования смарт-контрактов Solidity, язык Rust изначально поддерживает операции с дробными числами. Однако операции с дробными числами имеют неизбежные проблемы с точностью вычислений. Поэтому при написании смарт-контрактов не рекомендуется использовать операции с дробными числами, особенно при обработке соотношений или процентных ставок, связанных с важными экономическими или финансовыми решениями.
В настоящее время основные языки программирования, представляющие числа с плавающей запятой, в основном следуют стандарту IEEE 754, и язык Rust не является исключением. Тип двойной точности с плавающей запятой f64 хранится в компьютере в виде двоичных данных.
Числа с плавающей запятой выражаются в научной нотации с основанием 2. Например, десятичное число 0,8125 можно представить с помощью конечного двоичного числа 0.1101. Однако для десятичного числа 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 или как финансовый или профессиональный совет. Подробности смотрите в разделе «Отказ от ответственности» .
Тонкости точных расчетов чисел в смарт-контрактах на Rust: избегайте ловушек с плавающей запятой
Rust смарт-контракты养成日记(7)数值精算
1. Проблемы точности с плавающей запятой
В отличие от распространённого языка программирования смарт-контрактов Solidity, язык Rust изначально поддерживает операции с дробными числами. Однако операции с дробными числами имеют неизбежные проблемы с точностью вычислений. Поэтому при написании смарт-контрактов не рекомендуется использовать операции с дробными числами, особенно при обработке соотношений или процентных ставок, связанных с важными экономическими или финансовыми решениями.
В настоящее время основные языки программирования, представляющие числа с плавающей запятой, в основном следуют стандарту IEEE 754, и язык Rust не является исключением. Тип двойной точности с плавающей запятой f64 хранится в компьютере в виде двоичных данных.
Числа с плавающей запятой выражаются в научной нотации с основанием 2. Например, десятичное число 0,8125 можно представить с помощью конечного двоичного числа 0.1101. Однако для десятичного числа 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, избегая ошибок или несправедливых результатов, вызванных проблемами с точностью.
!