Phát triển hợp đồng thông minh Rust: Kỹ thuật tính toán số và kiểm soát độ chính xác

Rust hợp đồng thông minh养成日记(7):数值精算

1. Vấn đề độ chính xác trong phép toán số thực

Ngôn ngữ Rust hỗ trợ tính toán số thực một cách tự nhiên, nhưng các phép toán số thực có vấn đề về độ chính xác không thể tránh khỏi. Khi viết hợp đồng thông minh, không nên sử dụng các phép toán số thực, đặc biệt là khi xử lý các tỷ lệ hoặc lãi suất liên quan đến quyết định kinh tế/tài chính quan trọng.

Loại số thực độ chính xác kép f64 trong ngôn ngữ Rust tuân theo tiêu chuẩn IEEE 754, sử dụng ký hiệu khoa học với cơ số là 2. Một số số thập phân như 0.7 không thể được biểu diễn chính xác bằng số thực có độ dài hữu hạn, dẫn đến hiện tượng "làm tròn".

Trong thử nghiệm phân phối 0.7 token NEAR cho mười người dùng trên chuỗi công khai NEAR, kết quả phép toán số thực không chính xác:

gỉ let amount: f64 = 0.7;
let divisor: f64 = 10.0; let result_0 = amount / divisor;

giá trị của amount là 0.69999999999999995559, giá trị của result_0 là 0.06999999999999999, không phải là 0.07 như mong đợi.

Để giải quyết vấn đề này, có thể sử dụng số cố định. Trong NEAR Protocol, thường sử dụng cách biểu diễn 1 NEAR = 10^24 yoctoNEAR:

gỉ let N: u128 = 1_000_000_000_000_000_000_000_000; let amount: u128 = 700_000_000_000_000_000_000_000; let divisor: u128 = 10; let result_0 = amount / divisor;

Cách này có thể đạt được kết quả tính toán chính xác: 0.7 NEAR / 10 = 0.07 NEAR.

2. Vấn đề độ chính xác trong tính toán số nguyên Rust

2.1 thứ tự hoạt động

Thứ tự của phép nhân và phép chia có cùng độ ưu tiên có thể ảnh hưởng trực tiếp đến kết quả tính toán. Ví dụ:

gỉ let a: u128 = 1_0000; let b: u128 = 10_0000; let c: u128 = 20;

// result_0 = a * c / b let result_0 = a.checked_mul(c).expect("ERR_MUL").checked_div(b).expect("ERR_DIV");

// result_1 = a / b * c
let result_1 = a.checked_div(b).expect("ERR_DIV").checked_mul(c).expect("ERR_MUL");

Kết quả của result_0 và result_1 khác nhau, vì đối với phép chia số nguyên, độ chính xác nhỏ hơn số chia sẽ bị bỏ qua.

2.2 quy mô quá nhỏ

Khi liên quan đến giá trị nhỏ, phép toán số nguyên có thể dẫn đến mất độ chính xác:

gỉ let a: u128 = 10; let b: u128 = 3; let c: u128 = 4; let decimal: u128 = 100_0000;

// result_0 = (a / b) * c let result_0 = a.checked_div(b).expect("ERR_DIV").checked_mul(c).expect("ERR_MUL");

// result_1 = (a * decimal / b) * c / decimal; let 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");

Kết quả của result_0 và result_1 khác nhau, result_1 gần với giá trị dự kiến thực tế hơn.

3. Làm thế nào để viết hợp đồng thông minh Rust cho tính toán số liệu

3.1 Điều chỉnh thứ tự thực hiện phép toán

Làm cho phép nhân số nguyên ưu tiên hơn phép chia số nguyên.

3.2 tăng bậc số nguyên

Sử dụng số lượng lớn hơn, tạo ra phân số lớn hơn. Ví dụ, biểu diễn 5.123 NEAR thành 51_230_000_000 yoctoNEAR.

3.3 Tích lũy tổn thất độ chính xác tính toán

Ghi lại tổn thất độ chính xác tính toán tích lũy, bù đắp trong các phép toán tiếp theo. Ví dụ:

rỉ sét u128 { let token_to_distribute = offset + amount; let per_user_share = token_to_distribute / USER_NUM; let recorded_offset = token_to_distribute - per_user_share * USER_NUM; recorded_offset }

( 3.4 Sử dụng thư viện Rust Crate rust-decimal

Thư viện này phù hợp cho các tính toán tài chính số thập phân cần độ chính xác hiệu quả và không có lỗi làm tròn.

) 3.5 Xem xét cơ chế làm tròn

Trong thiết kế hợp đồng thông minh, vấn đề làm tròn thường áp dụng nguyên tắc "Tôi muốn hưởng lợi, người khác không được thu lợi từ tôi". Tùy theo tình huống mà chọn làm tròn xuống, làm tròn lên hoặc làm tròn gần nhất.

![]###https://img-cdn.gateio.im/webp-social/moments-6e8b4081214a69423fc7ae022d05c728.webp###

TOKEN3.16%
NUM1.08%
Xem bản gốc
Trang này có thể chứa nội dung của bên thứ ba, được cung cấp chỉ nhằm mục đích thông tin (không phải là tuyên bố/bảo đảm) và không được coi là sự chứng thực cho quan điểm của Gate hoặc là lời khuyên về tài chính hoặc chuyên môn. Xem Tuyên bố từ chối trách nhiệm để biết chi tiết.
  • Phần thưởng
  • 3
  • Chia sẻ
Bình luận
0/400
BearMarketBuildervip
· 08-05 07:58
Hố số thực này thật sâu như biển.
Xem bản gốcTrả lời0
SelfSovereignStevevip
· 08-05 07:53
Số thực quá tệ, hợp đồng thông minh chắc chắn sẽ nổ, hoàn toàn không dám sử dụng.
Xem bản gốcTrả lời0
DegenGamblervip
· 08-05 07:49
Các anh em chơi Rust chú ý nhé, cái bẫy độ chính xác này không nhỏ.
Xem bản gốcTrả lời0
Giao dịch tiền điện tử mọi lúc mọi nơi
qrCode
Quét để tải xuống ứng dụng Gate
Cộng đồng
Tiếng Việt
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)