Diario de desarrollo de contratos inteligentes en Rust (7) Cálculo numérico
1. Problemas de precisión en operaciones de punto flotante
A diferencia de los lenguajes de programación de contratos inteligentes comunes como Solidity, el lenguaje Rust admite de forma nativa operaciones de punto flotante. Sin embargo, las operaciones de punto flotante presentan problemas de precisión de cálculo que son inevitables. Por lo tanto, al redactar contratos inteligentes, no se recomienda el uso de operaciones de punto flotante, especialmente al tratar con razones o tasas de interés que involucren decisiones económicas o financieras importantes.
Actualmente, la mayoría de los lenguajes de programación de uso común que representan números de punto flotante siguen el estándar IEEE 754, y el lenguaje Rust no es una excepción. El tipo de punto flotante de doble precisión f64 se almacena internamente en la computadora en forma de datos binarios.
Los números de punto flotante se expresan utilizando notación científica con base 2. Por ejemplo, el número decimal 0.8125 se puede representar con el número binario de longitud finita 0.1101. Sin embargo, para un número decimal como 0.7, el proceso de conversión a punto flotante resultará en una representación binaria que se repite infinitamente, y no se puede representar con un número de punto flotante de longitud finita de manera precisa, lo que da lugar a un fenómeno de "redondeo".
Supongamos que se necesitan distribuir 0.7 tokens a diez usuarios, la cantidad de tokens que recibe cada usuario se calculará y se guardará en la variable result_0. Después de ejecutar los casos de prueba relacionados, podemos ver que el valor de amount no representa con precisión 0.7, sino un valor muy aproximado de 0.69999999999999995559. Además, para la operación de división única amount/divisor, el resultado de la operación también se vuelve inexacto, siendo 0.06999999999999999, y no el esperado 0.07. Esto muestra la incertidumbre de las operaciones con números de punto flotante.
Para ello, necesitamos considerar el uso de otros tipos de métodos de representación numérica en contratos inteligentes, como los números de punto fijo. En la redacción real de contratos inteligentes, a menudo se utiliza una fracción con un denominador fijo para representar un valor, como la fracción x/N, donde N es una constante y x puede variar.
En algunas cadenas de bloques públicas, el valor común de N es 10^24, es decir, 10^24 unidades mínimas son equivalentes a 1 unidad del token principal. Basado en esto, podemos cambiar las operaciones de punto flotante a operaciones enteras para obtener resultados de cálculo más precisos.
2. Problemas de precisión en el cálculo de enteros en Rust
El uso de operaciones enteras puede resolver el problema de la pérdida de precisión en las operaciones de punto flotante en ciertos escenarios. Pero esto no significa que los resultados de los cálculos enteros sean completamente precisos y confiables. Algunas de las razones que afectan la precisión de los cálculos enteros incluyen:
2.1 orden de operaciones
El orden de las operaciones de multiplicación y división con la misma prioridad aritmética puede afectar directamente el resultado del cálculo, lo que lleva a problemas de precisión en los cálculos enteros. En el caso de la división entera, la precisión inferior al divisor se descartará. Por lo tanto, en ciertos procesos de cálculo, realizar primero la operación de división puede resultar en una pérdida de precisión.
2.2 escala demasiado pequeña
Cuando los valores involucrados son demasiado pequeños, las operaciones enteras también pueden presentar problemas de precisión. Por ejemplo, en algunos casos, realizar operaciones enteras directamente y realizar cálculos después de introducir un orden de magnitud mayor puede dar resultados diferentes.
3. Cómo escribir contratos inteligentes de cálculo numérico en Rust
Para garantizar la precisión de cálculo en los contratos inteligentes, se pueden tomar las siguientes medidas de protección:
3.1 Ajustar el orden de las operaciones
Intenta que la multiplicación de enteros tenga prioridad sobre la división de enteros.
3.2 aumentar el orden de magnitud de un entero
Usar un rango mayor para representar valores, creando moléculas más grandes para participar en operaciones, con el fin de aumentar la precisión.
3.3 Pérdida de precisión en la acumulación de operaciones
Para los problemas de precisión de cálculo de enteros que no se pueden evitar, se puede considerar registrar la pérdida de precisión acumulada en los cálculos. En cálculos posteriores, se deben tener en cuenta estas pérdidas para lograr una distribución de resultados más justa.
3.4 Uso de la biblioteca Rust Crate rust-decimal
Esta biblioteca es adecuada para escenarios de cálculo financiero con decimales que requieren alta precisión y sin error de redondeo.
3.5 Considerar el mecanismo de redondeo
Al diseñar contratos inteligentes, los problemas de redondeo suelen seguir el principio de "beneficioso para uno mismo, perjudicial para los demás". Elija redondear hacia abajo, hacia arriba o de otra manera adecuada según la situación específica.
Al implementar estas medidas, se puede lograr un cálculo numérico más preciso en los contratos inteligentes de Rust, evitando errores o resultados injustos debido a problemas de precisión.
Ver originales
Esta página puede contener contenido de terceros, que se proporciona únicamente con fines informativos (sin garantías ni declaraciones) y no debe considerarse como un respaldo por parte de Gate a las opiniones expresadas ni como asesoramiento financiero o profesional. Consulte el Descargo de responsabilidad para obtener más detalles.
13 me gusta
Recompensa
13
10
Republicar
Compartir
Comentar
0/400
SeasonedInvestor
· 07-19 12:17
La precisión realmente es un problema.
Ver originalesResponder0
RugPullProphet
· 07-18 09:14
El control de precisión debe estar en su lugar.
Ver originalesResponder0
GasOptimizer
· 07-16 19:00
La precisión es vida
Ver originalesResponder0
TestnetScholar
· 07-16 18:56
Ir a la cuenta entera es más confiable
Ver originalesResponder0
GasFeeBarbecue
· 07-16 18:46
La tasa multiplicada por 10000
Ver originalesResponder0
GweiWatcher
· 07-16 18:46
Hay demasiadas trampas de precisión.
Ver originalesResponder0
MetaverseHermit
· 07-16 18:32
La actuaria decide la puerta de la vida y la muerte
Técnicas de cálculo numérico en contratos inteligentes en Rust: evitar trampas de punto flotante
Diario de desarrollo de contratos inteligentes en Rust (7) Cálculo numérico
1. Problemas de precisión en operaciones de punto flotante
A diferencia de los lenguajes de programación de contratos inteligentes comunes como Solidity, el lenguaje Rust admite de forma nativa operaciones de punto flotante. Sin embargo, las operaciones de punto flotante presentan problemas de precisión de cálculo que son inevitables. Por lo tanto, al redactar contratos inteligentes, no se recomienda el uso de operaciones de punto flotante, especialmente al tratar con razones o tasas de interés que involucren decisiones económicas o financieras importantes.
Actualmente, la mayoría de los lenguajes de programación de uso común que representan números de punto flotante siguen el estándar IEEE 754, y el lenguaje Rust no es una excepción. El tipo de punto flotante de doble precisión f64 se almacena internamente en la computadora en forma de datos binarios.
Los números de punto flotante se expresan utilizando notación científica con base 2. Por ejemplo, el número decimal 0.8125 se puede representar con el número binario de longitud finita 0.1101. Sin embargo, para un número decimal como 0.7, el proceso de conversión a punto flotante resultará en una representación binaria que se repite infinitamente, y no se puede representar con un número de punto flotante de longitud finita de manera precisa, lo que da lugar a un fenómeno de "redondeo".
Supongamos que se necesitan distribuir 0.7 tokens a diez usuarios, la cantidad de tokens que recibe cada usuario se calculará y se guardará en la variable result_0. Después de ejecutar los casos de prueba relacionados, podemos ver que el valor de amount no representa con precisión 0.7, sino un valor muy aproximado de 0.69999999999999995559. Además, para la operación de división única amount/divisor, el resultado de la operación también se vuelve inexacto, siendo 0.06999999999999999, y no el esperado 0.07. Esto muestra la incertidumbre de las operaciones con números de punto flotante.
Para ello, necesitamos considerar el uso de otros tipos de métodos de representación numérica en contratos inteligentes, como los números de punto fijo. En la redacción real de contratos inteligentes, a menudo se utiliza una fracción con un denominador fijo para representar un valor, como la fracción x/N, donde N es una constante y x puede variar.
En algunas cadenas de bloques públicas, el valor común de N es 10^24, es decir, 10^24 unidades mínimas son equivalentes a 1 unidad del token principal. Basado en esto, podemos cambiar las operaciones de punto flotante a operaciones enteras para obtener resultados de cálculo más precisos.
2. Problemas de precisión en el cálculo de enteros en Rust
El uso de operaciones enteras puede resolver el problema de la pérdida de precisión en las operaciones de punto flotante en ciertos escenarios. Pero esto no significa que los resultados de los cálculos enteros sean completamente precisos y confiables. Algunas de las razones que afectan la precisión de los cálculos enteros incluyen:
2.1 orden de operaciones
El orden de las operaciones de multiplicación y división con la misma prioridad aritmética puede afectar directamente el resultado del cálculo, lo que lleva a problemas de precisión en los cálculos enteros. En el caso de la división entera, la precisión inferior al divisor se descartará. Por lo tanto, en ciertos procesos de cálculo, realizar primero la operación de división puede resultar en una pérdida de precisión.
2.2 escala demasiado pequeña
Cuando los valores involucrados son demasiado pequeños, las operaciones enteras también pueden presentar problemas de precisión. Por ejemplo, en algunos casos, realizar operaciones enteras directamente y realizar cálculos después de introducir un orden de magnitud mayor puede dar resultados diferentes.
3. Cómo escribir contratos inteligentes de cálculo numérico en Rust
Para garantizar la precisión de cálculo en los contratos inteligentes, se pueden tomar las siguientes medidas de protección:
3.1 Ajustar el orden de las operaciones
Intenta que la multiplicación de enteros tenga prioridad sobre la división de enteros.
3.2 aumentar el orden de magnitud de un entero
Usar un rango mayor para representar valores, creando moléculas más grandes para participar en operaciones, con el fin de aumentar la precisión.
3.3 Pérdida de precisión en la acumulación de operaciones
Para los problemas de precisión de cálculo de enteros que no se pueden evitar, se puede considerar registrar la pérdida de precisión acumulada en los cálculos. En cálculos posteriores, se deben tener en cuenta estas pérdidas para lograr una distribución de resultados más justa.
3.4 Uso de la biblioteca Rust Crate rust-decimal
Esta biblioteca es adecuada para escenarios de cálculo financiero con decimales que requieren alta precisión y sin error de redondeo.
3.5 Considerar el mecanismo de redondeo
Al diseñar contratos inteligentes, los problemas de redondeo suelen seguir el principio de "beneficioso para uno mismo, perjudicial para los demás". Elija redondear hacia abajo, hacia arriba o de otra manera adecuada según la situación específica.
Al implementar estas medidas, se puede lograr un cálculo numérico más preciso en los contratos inteligentes de Rust, evitando errores o resultados injustos debido a problemas de precisión.