Tôi có bit sau đây, tuy nhiên khi biên dịch với GCC 4.4 với các cờ tối ưu hóa khác nhau, tôi nhận được một số kết quả không mong muốn khi chạy.Vấn đề GCC với so sánh hai loại thô
#include <iostream>
int main()
{
const unsigned int cnt = 10;
double lst[cnt] = { 0.0 };
const double v[4] = { 131.313, 737.373, 979.797, 731.137 };
for(unsigned int i = 0; i < cnt; ++i) {
lst[i] = v[i % 4] * i;
}
for(unsigned int i = 0; i < cnt; ++i) {
double d = v[i % 4] * i;
if(lst[i] != d) {
std::cout << "error @ : " << i << std::endl;
return 1;
}
}
return 0;
}
khi biên soạn với: "g ++ -pedantic Wall -Werror -O1 -o test test.cpp" tôi nhận được kết quả như sau: "Lỗi @: 3"
khi biên soạn với: "g ++ -pedantic Wall -Werror -O2 -o test test.cpp" tôi nhận được kết quả như sau: "lỗi @: 3"
khi biên soạn với: "g ++ -pedantic Wall -Werror O3 -o test test.cpp" tôi nhận được không có lỗi
khi biên soạn với: "g ++ -pedantic Wall - Werror -o test test.cpp" tôi nhận được không có lỗi
tôi không tin rằng đây là một vấn đề liên quan đến làm tròn, hoặc chênh lệch epsilon trong so sánh. Tôi đã thử điều này với Intel v10 và MSVC 9,0 và tất cả họ dường như làm việc như mong đợi. Tôi tin rằng điều này sẽ không có gì hơn một so sánh bitwise.
Nếu tôi thay thế if-tuyên bố như sau: if (static_cast<long long int>(lst[i]) != static_cast<long long int>(d))
, và thêm "-Wno dài dài" tôi nhận được không có lỗi trong bất kỳ chế độ tối ưu hóa khi chạy.
Nếu tôi thêm std::cout << d << std::endl;
trước khi "return 1", tôi nhận được không có lỗi trong bất kỳ chế độ tối ưu hóa khi chạy.
Đây có phải là lỗi trong mã của tôi hay không, có điều gì sai với GCC và cách xử lý loại kép không?
Lưu ý: Tôi vừa thử với phiên bản gcc 4.3 và 3.3, lỗi không được hiển thị.
Độ phân giải: Mike Dinsdale ghi nhận trong báo cáo lỗi sau: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 Có vẻ như đội GCC không hoàn toàn chắc chắn về bản chất của vấn đề.
Như được đề xuất trong báo cáo lỗi, độ phân giải có thể là sử dụng tùy chọn lưu trữ ffloat. Tôi đã thử điều này và nó hoạt động, tuy nhiên kết quả từ một quan điểm thực hiện không phải là tuyệt vời, mặc dù ymmv.
So sánh 'gấp đôi' được thực hiện tốt nhất bằng cách sử dụng một giá trị delta nhỏ để tính toán các điểm không chính xác. Thử in các giá trị của 'lst [i]' và 'd' ngay trước khi so sánh và cho chúng ta biết chúng khác nhau như thế nào. – dirkgently
Đây không phải là một kịch bản mà tôi có giá trị được tạo từ các nguồn khác nhau và tôi muốn xem liệu chúng có bằng nhau hay không, đây là những giá trị giống nhau (bitwise), chúng nên so sánh đúng. Thực tế là trình biên dịch không tạo ra một tệp nhị phân cung cấp một tập hợp đầu ra nhất quán hoặc là cách đáng lo ngại. –
@Monomer: Hãy xem xét rằng khi bạn thay đổi chương trình để sử dụng một so sánh bitwise isntead của FPU, bạn đang thay đổi lắp ráp. Có vẻ cơ bản, nhưng điều này có nghĩa là nó sẽ không sử dụng các giá trị trên FPU, có thể bị tắt, và thực sự tải và có thể cắt bớt chúng. Nói một cách đơn giản, bài kiểm tra của bạn không kết luận. – GManNickG