xem xét mã # C sau:Tại sao trật tự ảnh hưởng đến làm tròn khi thêm nhiều đôi trong C#
double result1 = 1.0 + 1.1 + 1.2;
double result2 = 1.2 + 1.0 + 1.1;
if (result1 == result2)
{
...
}
result1 nên luôn bằng result2 phải không? Vấn đề là, nó không. result1 là 3,3 và result2 là 3.3000000000000003. Sự khác biệt duy nhất là thứ tự của các hằng số.
Tôi biết rằng việc tăng gấp đôi được triển khai theo cách mà các vấn đề làm tròn có thể xảy ra. Tôi biết rằng tôi có thể sử dụng số thập phân thay vì nếu tôi cần độ chính xác tuyệt đối. Hoặc tôi có thể sử dụng Math.Round() trong câu lệnh if của tôi. Tôi chỉ là một mọt sách, những người muốn hiểu những gì trình biên dịch C# đang làm. Bất cứ ai có thể cho tôi biết?
Edit:
Nhờ tất cả những người ấy cho đến nay đề nghị đọc lên trên nổi điểm số học và/hoặc nói về sự thiếu chính xác vốn có của cách CPU xử lý gấp đôi. Nhưng tôi cảm thấy lực đẩy chính của câu hỏi của tôi vẫn chưa được trả lời. Đó là lỗi của tôi vì không nói đúng cách. Hãy để tôi đặt nó như thế này:
Breaking xuống mã trên, tôi mong chờ các hoạt động sau đây để thể xảy ra:
double r1 = 1.1 + 1.2;
double r2 = 1.0 + r1
double r3 = 1.0 + 1.1
double r4 = 1.2 + r3
Giả sử rằng mỗi người trong số những bổ sung ở trên có làm tròn lỗi (đánh số e1. .e 4). Vì vậy, r1 chứa lỗi làm tròn e1, r2 bao gồm các lỗi làm tròn e1 + e2, r3 chứa e3 và r4 chứa e3 + e4.
Bây giờ, tôi không biết chính xác cách các lỗi làm tròn xảy ra nhưng tôi đã dự kiến e1 + e2 bằng e3 + e4. Rõ ràng là không, nhưng điều đó có vẻ không đúng với tôi. Một điều nữa là khi tôi chạy mã trên, tôi không nhận được bất kỳ lỗi làm tròn nào. Đó là những gì làm cho tôi nghĩ rằng đó là trình biên dịch C# đó là làm một cái gì đó kỳ lạ chứ không phải là CPU.
Tôi biết tôi đang hỏi rất nhiều và có thể câu trả lời hay nhất mà mọi người có thể đưa ra là đi và làm PHD trong thiết kế CPU, nhưng tôi chỉ nghĩ rằng tôi sẽ hỏi.
Chỉnh sửa 2
Nhìn vào IL từ mẫu mã ban đầu của tôi, thì rõ ràng rằng đó là trình biên dịch không phải là CPU đó là làm điều này:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 1
.locals init (
[0] float64 result1,
[1] float64 result2)
L_0000: nop
L_0001: ldc.r8 3.3
L_000a: stloc.0
L_000b: ldc.r8 3.3000000000000003
L_0014: stloc.1
L_0015: ret
}
Trình biên dịch là thêm lên những con số cho tôi!
+1 ví dụ cụ thể tốt – bobince
Ví dụ là tốt, nhưng bạn đã thay đổi thứ tự của các hoạt động so với mã ban đầu. OP đã làm như vậy trong lần chỉnh sửa đầu tiên. –