Điều này có vẻ là một vấn đề về cuối cùng, nhưng không phải là vấn đề lớn về nội dung của bạn và vấn đề nhỏ bé. ARM đôi khi sử dụng một thứ tự byte bất thường cho double
. Từ "Sổ tay của Floating-Point Arithmetic" của Jean-Michel Muller, et al .:
... số lượng tăng gấp đôi độ chính xác đó là gần nhất với -7.0868766365730135 x 10^-268
được mã hóa bởi một chuỗi các byte 11 22 33 44 55 66 77 88
trong bộ nhớ (từ thấp nhất đến cao nhất một) trên x86 và Linux/IA-64 nền tảng (họ được cho là ít về cuối nhỏ) và bởi 88 77 66 55 44 33 22 11
trên hầu hết các nền tảng PowerPC (họ được cho là lớn về cuối nhỏ). Một số kiến trúc, chẳng hạn như như IA-64, ARM và PowerPC được gọi là bi-endian. tức là, họ có thể hoặc là người nhỏ tuổi hoặc người lớn tuổi tùy thuộc vào cấu hình của họ.
Có một ngoại lệ: một số nền tảng dựa trên ARM. Bộ vi xử lý ARM theo truyền thống đã sử dụng máy gia tốc điểm nổi (FPA) , trong đó các số chính xác kép được phân tách thành hai từ 32 bit theo thứ tự lớn và được lưu trữ theo số cuối cùng của máy , tức là, người nhỏ tuổi nói chung, có nghĩa là rằng số trên được mã hóa theo trình tự 55 66 77 88 11 22 33 44
. ARM gần đây đã giới thiệu một kiến trúc mới cho dấu phẩy động số học: vectơ dấu phẩy động (VFP), trong đó các từ được lưu trữ theo thứ tự byte gốc của bộ xử lý.
Khi nhìn theo một thứ tự byte lớn về cuối nhỏ, M_PI
sẽ có một đại diện trông giống như:
0x400921fb54442d18
Số lớn xấp xỉ bằng 8.6192e+97
wil có một đại diện trông giống như:
0x54442d18400921fb
Nếu bạn nhìn kỹ, hai từ 32 bit được hoán đổi, nhưng thứ tự byte trong các từ 32 bit là giống nhau. Vì vậy, rõ ràng, định dạng điểm kép 'ARM' truyền thống dường như gây nhầm lẫn cho thư viện Qt (hoặc thư viện Qt bị định cấu hình sai).
Tôi không chắc liệu bộ xử lý có đang sử dụng định dạng truyền thống hay không và Qt dự kiến nó sẽ ở định dạng VFP, hoặc nếu mọi thứ theo cách khác. Nhưng nó có vẻ là một trong hai tình huống đó.
Tôi cũng không chắc chắn chính xác cách khắc phục sự cố - tôi đoán có một số tùy chọn để xây dựng Qt để xử lý chính xác.
đoạn sau đây sẽ ít nhất là cho bạn biết định dạng cho double
trình biên dịch được sử dụng, có thể giúp bạn thu hẹp những gì cần phải thay đổi trong Qt:
unsigned char* b;
unsigned char* e;
double x = -7.0868766365730135e-268;
b = (unsigned char*) &x;
e = b + sizeof(x);
for (; b != e; ++b) {
printf("%02x ", *b);
}
puts("");
Một đồng bằng máy ít về cuối nhỏ sẽ hiển thị:
11 22 33 44 55 66 77 88
cập nhật với phân tích thêm một chút:
Hiện tại, tôi không thể thực hiện bất kỳ việc gỡ lỗi thực sự nào (tôi thậm chí không có quyền truy cập vào máy trạm của mình), nhưng bằng cách xem nguồn Qt có sẵn trên http://qt.gitorious.org đây là phân tích bổ sung:
Dường như các cuộc gọi Qt đến hàm QLocalePrivate::doubleToString()
trong qlocale.cpp để chuyển đổi một số double
thành dạng chữ và số.
Nếu Qt được biên dịch với QT_QLOCALE_USES_FCVT
được xác định, thì QLocalePrivate::doubleToString()
sẽ sử dụng chức năng fcvt()
của nền tảng này để thực hiện chuyển đổi. Nếu QT_QLOCALE_USES_FCVT
là không phải được xác định, thì QLocalePrivate::doubleToString()
kết thúc bằng cách gọi _qdtoa()
để thực hiện chuyển đổi. Hàm đó kiểm tra các trường khác nhau của số double
trực tiếp và dường như giả định rằng double
ở dạng nghiêm ngặt hoặc nhỏ gọn (ví dụ: sử dụng các hàm getWord0()
và getWord1()
để nhận từ thấp và cao tương ứng của double
tương ứng).
Xem http://qt.gitorious.org/qt/qt/blobs/HEAD/src/corelib/tools/qlocale.cpp và http://qt.gitorious.org/qt/qt/blobs/HEAD/src/corelib/tools/qlocale_tools.cpp hoặc bản sao tệp của riêng bạn để biết chi tiết.
Giả sử rằng nền tảng của bạn đang sử dụng biểu diễn FPA ARM truyền thống cho double
(trong đó các nửa 32 bit của double
được lưu trữ theo thứ tự lớn bất kể hệ thống tổng thể có nhỏ gọn), tôi nghĩ bạn ' sẽ cần phải xây dựng Qt với số QT_QLOCALE_USES_FCVT
được xác định. Tôi tin rằng tất cả những gì bạn cần làm là vượt qua tùy chọn -DQT_QLOCALE_USES_FCVT
cho kịch bản cấu hình khi xây dựng Qt.
Tôi đã thêm một chút về những gì dường như đang xảy ra bên trong Qt cùng với những gì tôi nghĩ là một giải pháp có thể. –
Được nghiên cứu kỹ. +1 –
Cảm ơn bạn đã trả lời chi tiết! Trên thực tế vấn đề là thiếu các tùy chọn '-DQT_QLOCALE_USES_FCVT'. Sau khi xây dựng lại mọi thứ đã hoạt động chính xác. Trước khi xây dựng lại đoạn trích của bạn, hãy in dòng sau: '55 66 77 88 11 22 33 44'. –