Không, đây không phải là câu hỏi "Tại sao (1 / 3.0) * 3! = 1" khác .
Gần đây tôi đã đọc về các điểm nổi rất nhiều; cụ thể, cách tính toán giống nhau có thể cho kết quả khác nhau trên các kiến trúc hoặc cài đặt tối ưu hóa khác nhau.
Đây là một vấn đề đối với các trò chơi video lưu trữ phát lại, hoặc được kết nối ngang hàng (trái ngược với máy khách-máy khách), phụ thuộc vào tất cả các máy khách tạo ra kết quả chính xác giống nhau mỗi khi chúng chạy chương trình - một sự khác biệt nhỏ trong một Tính toán dấu phẩy động có thể dẫn đến trạng thái trò chơi khác nhau mạnh mẽ trên các máy khác nhau (hoặc thậm chí trên cùng một máy! )
Điều này xảy ra ngay cả trong số các bộ xử lý "theo" IEEE-754 , chủ yếu là do một số bộ xử lý (cụ thể là x86) sử dụng độ chính xác mở rộng gấp đôi . Nghĩa là, họ sử dụng các thanh ghi 80 bit để thực hiện tất cả các phép tính, sau đó cắt ngắn thành 64 hoặc 32 bit, dẫn đến kết quả làm tròn khác với các máy sử dụng các bit 64 hoặc 32 bit để tính toán.
Tôi đã thấy một số giải pháp cho vấn đề này trực tuyến, nhưng tất cả cho C ++, không phải C #:
- Vô hiệu hóa chế độ chính xác mở rộng gấp đôi (để tất cả các
double
tính toán sử dụng IEEE-754 64 bit) bằng cách sử dụng_controlfp_s
(Windows),_FPU_SETCW
(Linux?) Hoặcfpsetprec
(BSD). - Luôn chạy cùng một trình biên dịch với cùng các cài đặt tối ưu hóa và yêu cầu tất cả người dùng phải có cùng kiến trúc CPU (không chơi đa nền tảng). Bởi vì "trình biên dịch" của tôi thực sự là JIT, có thể tối ưu hóa khác nhau mỗi khi chương trình được chạy , tôi không nghĩ rằng điều này là có thể.
- Sử dụng số học điểm cố định, và tránh
float
vàdouble
hoàn toàn.decimal
sẽ hoạt động cho mục đích này, nhưng sẽ chậm hơn nhiều và không cóSystem.Math
chức năng thư viện nào hỗ trợ nó.
Vì vậy, điều này thậm chí là một vấn đề trong C #? Nếu tôi chỉ có ý định hỗ trợ Windows (không phải Mono) thì sao?
Nếu có, có cách nào để buộc chương trình của tôi chạy ở độ chính xác kép bình thường không?
Nếu không, có thư viện nào giúp duy trì tính toán dấu phẩy động nhất quán không?
strictfp
từ khóa, buộc tất cả các tính toán phải được thực hiện theo kích thước đã nêu ( float
hoặc double
) thay vì kích thước mở rộng. Tuy nhiên, Java vẫn có nhiều vấn đề với hỗ trợ IEE-754. Rất (rất, rất) rất ít ngôn ngữ lập trình hỗ trợ IEE-754 tốt.