Diário de Desenvolvimento de Contratos Inteligentes em Rust (7) Cálculo de Valores
1. Problemas de precisão em operações de ponto flutuante
Diferente das linguagens de programação de contratos inteligentes comuns como Solidity, a linguagem Rust suporta nativamente operações de ponto flutuante. No entanto, as operações de ponto flutuante apresentam problemas de precisão de cálculo que não podem ser evitados. Portanto, ao escrever contratos inteligentes, não é recomendado usar operações de ponto flutuante, especialmente ao lidar com razões ou taxas que envolvem decisões econômicas ou financeiras importantes.
As linguagens de programação mais populares atualmente para representar números de ponto flutuante seguem, na sua maioria, o padrão IEEE 754, e a linguagem Rust não é exceção. O tipo de ponto flutuante de dupla precisão f64 é armazenado internamente no computador na forma de dados binários.
Os números de ponto flutuante são expressos em notação científica com base 2. Por exemplo, o número binário de pontos fixos 0.1101 pode ser usado para representar o decimal 0.8125. No entanto, para um decimal como 0.7, durante o processo de conversão para ponto flutuante, haverá uma representação binária que se torna uma repetição infinita, não podendo ser representada com precisão por um número de ponto flutuante de comprimento finito, resultando em um fenômeno de "arredondamento".
Suponha que precisamos distribuir 0.7 tokens para dez usuários, e a quantidade de tokens que cada usuário recebe será calculada e armazenada na variável result_0. Após a execução dos casos de teste relacionados, podemos descobrir que o valor de amount não representa com precisão 0.7, mas sim um valor extremamente próximo de 0.69999999999999995559. Além disso, para a operação de divisão única amount/divisor, o resultado da operação também se tornará impreciso em 0.06999999999999999, e não o esperado 0.07. Isso demonstra a incerteza das operações com números de ponto flutuante.
Para isso, precisamos considerar o uso de outros tipos de representação numérica em contratos inteligentes, como números de ponto fixo. Na prática da redação de contratos inteligentes, normalmente é utilizado uma fração com um denominador fixo para representar um determinado valor, como a fração x/N, onde N é uma constante e x pode variar.
Em algumas blockchains públicas, o valor comum de N é 10^24, ou seja, 10^24 unidades mínimas equivalem a 1 unidade de token principal. Com base nisso, podemos converter operações de ponto flutuante em operações inteiras, para obter resultados de cálculo mais precisos.
2. Problemas de precisão em cálculos inteiros Rust
O uso de operações inteiras pode resolver o problema da perda de precisão em operações de ponto flutuante em certos cenários. Mas isso não significa que os resultados dos cálculos inteiros sejam completamente precisos e confiáveis. Algumas das razões que afetam a precisão dos cálculos inteiros incluem:
2.1 ordem das operações
A mudança na ordem de multiplicação e divisão com a mesma prioridade aritmética pode afetar diretamente o resultado do cálculo, levando a problemas de precisão em cálculos inteiros. No caso da divisão inteira, a precisão inferior ao divisor será descartada. Portanto, em certos processos de cálculo, realizar a operação de divisão primeiro pode resultar em perda de precisão.
2.2 quantidade muito pequena
Quando os valores envolvidos são muito pequenos, a operação com inteiros pode também apresentar problemas de precisão. Por exemplo, em certas situações, realizar operações inteiras diretamente e depois operar com uma magnitude maior pode levar a resultados diferentes.
3. Como escrever contratos inteligentes Rust para avaliação numérica
Para garantir a precisão dos cálculos nos contratos inteligentes, podem ser adotadas as seguintes medidas de proteção:
3.1 Ajustar a ordem das operações
Tente fazer com que a multiplicação de inteiros tenha prioridade sobre a divisão de inteiros.
3.2 aumentar a magnitude dos números inteiros
Usar uma ordem de grandeza maior para representar valores, criando numeradores maiores para participar nos cálculos, a fim de aumentar a precisão.
3.3 perda de precisão nos cálculos acumulados
Para os problemas de precisão de cálculo de inteiros que não podem ser evitados, pode-se considerar registrar a perda de precisão acumulada. Nas operações subsequentes, essas perdas devem ser levadas em conta para alcançar uma distribuição de resultados mais justa.
3.4 Usando a biblioteca Rust Crate rust-decimal
Esta biblioteca é adequada para cenários de cálculo financeiro decimal que requerem alta precisão e que não apresentam erros de arredondamento.
3.5 Considerar o mecanismo de arredondamento
Ao projetar contratos inteligentes, os problemas de arredondamento geralmente seguem o princípio de "favorecer a si mesmo, prejudicar os outros". Escolha arredondar para baixo, arredondar para cima ou outro método de arredondamento adequado, dependendo da situação específica.
Ao adotar essas medidas, é possível implementar cálculos numéricos mais precisos em contratos inteligentes Rust, evitando erros ou resultados injustos devido a problemas de precisão.
Ver original
Esta página pode conter conteúdos de terceiros, que são fornecidos apenas para fins informativos (sem representações/garantias) e não devem ser considerados como uma aprovação dos seus pontos de vista pela Gate, nem como aconselhamento financeiro ou profissional. Consulte a Declaração de exoneração de responsabilidade para obter mais informações.
Técnicas de cálculo de valores em contratos inteligentes Rust: evitar armadilhas de ponto flutuante
Diário de Desenvolvimento de Contratos Inteligentes em Rust (7) Cálculo de Valores
1. Problemas de precisão em operações de ponto flutuante
Diferente das linguagens de programação de contratos inteligentes comuns como Solidity, a linguagem Rust suporta nativamente operações de ponto flutuante. No entanto, as operações de ponto flutuante apresentam problemas de precisão de cálculo que não podem ser evitados. Portanto, ao escrever contratos inteligentes, não é recomendado usar operações de ponto flutuante, especialmente ao lidar com razões ou taxas que envolvem decisões econômicas ou financeiras importantes.
As linguagens de programação mais populares atualmente para representar números de ponto flutuante seguem, na sua maioria, o padrão IEEE 754, e a linguagem Rust não é exceção. O tipo de ponto flutuante de dupla precisão f64 é armazenado internamente no computador na forma de dados binários.
Os números de ponto flutuante são expressos em notação científica com base 2. Por exemplo, o número binário de pontos fixos 0.1101 pode ser usado para representar o decimal 0.8125. No entanto, para um decimal como 0.7, durante o processo de conversão para ponto flutuante, haverá uma representação binária que se torna uma repetição infinita, não podendo ser representada com precisão por um número de ponto flutuante de comprimento finito, resultando em um fenômeno de "arredondamento".
Suponha que precisamos distribuir 0.7 tokens para dez usuários, e a quantidade de tokens que cada usuário recebe será calculada e armazenada na variável result_0. Após a execução dos casos de teste relacionados, podemos descobrir que o valor de amount não representa com precisão 0.7, mas sim um valor extremamente próximo de 0.69999999999999995559. Além disso, para a operação de divisão única amount/divisor, o resultado da operação também se tornará impreciso em 0.06999999999999999, e não o esperado 0.07. Isso demonstra a incerteza das operações com números de ponto flutuante.
Para isso, precisamos considerar o uso de outros tipos de representação numérica em contratos inteligentes, como números de ponto fixo. Na prática da redação de contratos inteligentes, normalmente é utilizado uma fração com um denominador fixo para representar um determinado valor, como a fração x/N, onde N é uma constante e x pode variar.
Em algumas blockchains públicas, o valor comum de N é 10^24, ou seja, 10^24 unidades mínimas equivalem a 1 unidade de token principal. Com base nisso, podemos converter operações de ponto flutuante em operações inteiras, para obter resultados de cálculo mais precisos.
2. Problemas de precisão em cálculos inteiros Rust
O uso de operações inteiras pode resolver o problema da perda de precisão em operações de ponto flutuante em certos cenários. Mas isso não significa que os resultados dos cálculos inteiros sejam completamente precisos e confiáveis. Algumas das razões que afetam a precisão dos cálculos inteiros incluem:
2.1 ordem das operações
A mudança na ordem de multiplicação e divisão com a mesma prioridade aritmética pode afetar diretamente o resultado do cálculo, levando a problemas de precisão em cálculos inteiros. No caso da divisão inteira, a precisão inferior ao divisor será descartada. Portanto, em certos processos de cálculo, realizar a operação de divisão primeiro pode resultar em perda de precisão.
2.2 quantidade muito pequena
Quando os valores envolvidos são muito pequenos, a operação com inteiros pode também apresentar problemas de precisão. Por exemplo, em certas situações, realizar operações inteiras diretamente e depois operar com uma magnitude maior pode levar a resultados diferentes.
3. Como escrever contratos inteligentes Rust para avaliação numérica
Para garantir a precisão dos cálculos nos contratos inteligentes, podem ser adotadas as seguintes medidas de proteção:
3.1 Ajustar a ordem das operações
Tente fazer com que a multiplicação de inteiros tenha prioridade sobre a divisão de inteiros.
3.2 aumentar a magnitude dos números inteiros
Usar uma ordem de grandeza maior para representar valores, criando numeradores maiores para participar nos cálculos, a fim de aumentar a precisão.
3.3 perda de precisão nos cálculos acumulados
Para os problemas de precisão de cálculo de inteiros que não podem ser evitados, pode-se considerar registrar a perda de precisão acumulada. Nas operações subsequentes, essas perdas devem ser levadas em conta para alcançar uma distribuição de resultados mais justa.
3.4 Usando a biblioteca Rust Crate rust-decimal
Esta biblioteca é adequada para cenários de cálculo financeiro decimal que requerem alta precisão e que não apresentam erros de arredondamento.
3.5 Considerar o mecanismo de arredondamento
Ao projetar contratos inteligentes, os problemas de arredondamento geralmente seguem o princípio de "favorecer a si mesmo, prejudicar os outros". Escolha arredondar para baixo, arredondar para cima ou outro método de arredondamento adequado, dependendo da situação específica.
Ao adotar essas medidas, é possível implementar cálculos numéricos mais precisos em contratos inteligentes Rust, evitando erros ou resultados injustos devido a problemas de precisão.