Tôi đã viết một ví dụ hướng dẫn cho một đồng nghiệp để cho anh ta thấy lý do tại sao thử nghiệm phao cho bình đẳng thường là một ý tưởng tồi. Ví dụ tôi đã đi với đã được thêm 0,1 lần mười, và so sánh với 1.0 (một trong những tôi đã được hiển thị trong lớp số giới thiệu của tôi). Tôi đã rất ngạc nhiên khi thấy rằng hai kết quả bằng (code + output).CLR JIT tối ưu hóa vi phạm nhân quả?
float @float = 0.0f;
for(int @int = 0; @int < 10; @int += 1)
{
@float += 0.1f;
}
Console.WriteLine(@float == 1.0f);
Một số điều tra cho thấy kết quả này không thể dựa vào (giống như bình đẳng nổi). Điều tôi ngạc nhiên nhất là việc thêm mã sau mã khác có thể thay đổi kết quả của phép tính (code + output). Lưu ý rằng ví dụ này có cùng mã và IL, với thêm một dòng C# được nối thêm.
float @float = 0.0f;
for(int @int = 0; @int < 10; @int += 1)
{
@float += 0.1f;
}
Console.WriteLine(@float == 1.0f);
Console.WriteLine(@float.ToString("G9"));
Tôi biết tôi không được sử dụng bình đẳng trên phao và do đó không nên quan tâm quá nhiều về điều này, nhưng tôi thấy nó khá ngạc nhiên, như mọi người đã thể hiện điều này. Làm công cụ sau bạn đã thực hiện một phép tính thay đổi giá trị của phép tính trước? Tôi không nghĩ đó là mô hình của những người tính toán thường có trong đầu họ.
Tôi không hoàn toàn bối rối, có vẻ như an toàn để cho rằng có một số loại tối ưu xảy ra trong trường hợp "bằng" thay đổi kết quả tính toán (xây dựng trong chế độ gỡ lỗi ngăn trường hợp "bằng"). Rõ ràng, tối ưu hóa bị bỏ qua khi CLR phát hiện ra rằng sau này nó sẽ cần hộp nổi.
Tôi đã tìm kiếm một chút nhưng không thể tìm thấy lý do cho hành vi này. Ai có thể dẫn tôi vào?
Câu trả lời hay. Tôi cũng sẽ không gọi nó là lỗi. Thêm một hiệu ứng phụ bất thường (và chắc chắn không ngờ). – Gobiner