thể trùng lặp:
Retain precision with Doubles in javaJava chính xác đôi với -hằng/bộ phận
Bạn có biết sự khác biệt giữa hai hoạt động này trong Java.
final double m1 = 11d/1e9; // gives 1.1e-8
final double m2 = 11d * 1e-9; // gives 1.1000000000000001e-8
Tôi thấy trong bytecode được tạo ra mà kết quả biên dịch trước của m2 không phải là điều tôi mong đợi.
Trong đầu ra của javap -verbose -c
tôi có thể nhìn thấy giá trị sau:
const #3 = double 1.1E-8d;
[...]
const #6 = double 1.1000000000000001E-8d;
Khi tôi sử dụng m1 hoặc m2 trong các biểu thức khác, tôi không có kết quả tương tự.
Khi tôi cố gắng điều tương tự trong C, m1 và m2 là đúng 1.1e-8
Tôi nghĩ rằng vấn đề của tôi là trong cách xử lý java đôi tính toán chính xác nhưng tôi không thể giải thích bản thân mình những gì tôi bỏ lỡ.
Ok đó là giải thích cho Java nhưng bây giờ tại sao khi tôi thực thi cùng một mã trong C tôi có tất cả độ chính xác mà tôi cần? – Joker
Trình biên dịch C sẽ tối ưu hóa mã * nhiều * xa hơn 'javac' sẽ. Điều này có nghĩa là nó có thể dịch '/ 1e-9' thành' * 1e9' vì a) nhanh hơn và b) chính xác hơn.Trình biên dịch của Java thực hiện rất ít tối ưu hóa, điều này còn lại với JIT, điều này cũng có nghĩa là mã tối ưu hóa và tối ưu hóa phải làm điều tương tự, nếu không bạn sẽ thấy thay đổi về hành vi trong khi chương trình đang chạy. Việc chuyển đổi một 'double' thành một String cũng khác nhau trong C và Java, nhưng nó ít có khả năng là nguyên nhân của sự khác biệt. Trong cả hai trường hợp, họ sử dụng cùng một FPU. –
Ngoài ra trình biên dịch C cũng có thể sử dụng các thanh ghi/tính toán điểm nổi 80bit mà máy tính của bạn có. Đây là nền tảng phụ thuộc và chỉ có sẵn trên bộ xử lý x86/x64. Java sẽ hoạt động giống nhau trên mọi nền tảng vì vậy sẽ chỉ sử dụng điểm nổi 64 bit ngay cả khi điểm nổi 80 bit có sẵn. –