Tôi đang viết một chương trình mô phỏng tiến hành theo các bước riêng biệt. Mô phỏng bao gồm nhiều nút, mỗi nút có một giá trị dấu phẩy động được liên kết với nó, được tính toán lại trên mỗi bước. Kết quả có thể là dương, âm hoặc bằng không.Làm thế nào tôi có thể nhận được hành vi chương trình nhất quán khi sử dụng phao nổi?
Trong trường hợp kết quả bằng không hoặc ít xảy ra điều gì đó. Cho đến nay điều này dường như đơn giản - Tôi chỉ có thể làm một cái gì đó như thế này cho mỗi nút:
if (value <= 0.0f) something_happens();
Một vấn đề đã phát sinh, tuy nhiên, sau khi một số thay đổi gần đây tôi thực hiện cho các chương trình trong đó tôi sắp xếp lại thứ tự mà tính toán nhất định được thực hiện. Trong một thế giới hoàn hảo, các giá trị sẽ vẫn xuất hiện tương tự sau khi sắp xếp lại, nhưng vì sự thiếu chính xác của biểu diễn dấu phẩy động, chúng xuất hiện rất khác nhau một chút. Vì các phép tính cho mỗi bước phụ thuộc vào kết quả của bước trước đó, những thay đổi nhỏ trong kết quả này có thể tích lũy thành các biến thể lớn hơn khi số tiền thu được mô phỏng.
Dưới đây là một chương trình ví dụ đơn giản thể hiện những hiện tượng tôi đang mô tả:
float f1 = 0.000001f, f2 = 0.000002f;
f1 += 0.000004f; // This part happens first here
f1 += (f2 * 0.000003f);
printf("%.16f\n", f1);
f1 = 0.000001f, f2 = 0.000002f;
f1 += (f2 * 0.000003f);
f1 += 0.000004f; // This time this happens second
printf("%.16f\n", f1);
Kết quả của chương trình này là
0.0000050000057854
0.0000050000062402
mặc dù Ngoài ra là hoán vì vậy cả hai kết quả nên giống nhau . Lưu ý: Tôi hiểu rõ lý do tại sao điều này đang xảy ra - đó không phải là vấn đề. Vấn đề là các biến thể này có thể có nghĩa là đôi khi một giá trị được sử dụng để đi ra âm trên bước N, kích hoạt something_happens(), bây giờ có thể xuất hiện một hoặc hai bước âm sớm hơn hoặc muộn hơn, có thể dẫn đến kết quả mô phỏng tổng thể rất khác nhau vì something_happens() có hiệu ứng lớn. Những gì tôi muốn biết là có một cách hay để quyết định khi nào something_happens() nên được kích hoạt mà sẽ không bị ảnh hưởng bởi các biến thể nhỏ trong kết quả tính toán do các hoạt động sắp xếp lại để hành vi các phiên bản mới hơn của chương trình của tôi sẽ nhất quán với các phiên bản cũ hơn.
Các giải pháp duy nhất mà tôi cho đến nay đã có thể nghĩ đến là sử dụng một số epsilon giá trị như thế này:
if (value < epsilon) something_happens();
nhưng vì các biến thể nhỏ trong các kết quả tích lũy theo thời gian tôi cần phải thực hiện epsilon khá lớn (tương đối nói) để đảm bảo rằng các biến thể không dẫn đến something_happens() được kích hoạt trên một bước khác. Có cách nào tốt hơn?
Tôi đã đọc this excellent article về so sánh điểm nổi, nhưng tôi không thấy cách bất kỳ phương pháp so sánh nào được mô tả có thể giúp tôi trong trường hợp này.
Lưu ý: Sử dụng giá trị số nguyên thay vì không phải là một tùy chọn.
Sửa khả năng sử dụng đôi thay vì nổi đã được nâng lên. Điều này sẽ không giải quyết được vấn đề của tôi vì các biến thể vẫn ở đó, chúng sẽ chỉ có độ lớn nhỏ hơn.
Nếu các biến thể nhỏ gây ra thay đổi lớn về đầu ra, điều đó có nghĩa là kết quả của bạn có độ chính xác thấp không? (Ngoài ra: tại sao phao không tăng gấp đôi?) –
Hãy cẩn thận: 'printf ("%. 16f \ n ", f1);' đây là một tác dụng phụ không mong muốn: nó sẽ chuyển đổi phao của bạn thành một số tăng gấp đôi không đáng kể. Một float, tôi nghĩ, độ chính xác 7 chữ số ở mức tối đa. –
Cách tiêu chuẩn là tổng các giá trị dấu phẩy động là: để sắp xếp chúng và tổng hợp từ nhỏ nhất đến lớn nhất, độ chính xác nhỏ nhất này mất đi. Cũng sử dụng đôi không nổi. –