2015-11-10 29 views
9

Tôi đang sử dụng trình biên dịch XC32 từ Microchip, dựa trên trình biên dịch C chuẩn.Giải thích 32 bit unsigned dài như Single Precision IEEE-754 Float trong C

Tôi đang đọc giá trị 32 bit từ thiết bị trên mạng RS485 và lưu trữ giá trị này trong khoảng thời gian chưa ký mà tôi đã nhập là DWORD.

ví dụ:

typedef DWORD unsigned long; 

Khi đứng, khi tôi định kiểu giá trị này cho một người phao, giá trị tôi nhận được về cơ bản là phiên bản floating point của nó là đại diện số nguyên và không phải là thích hợp IEEE-754 giải thích nổi.

tức

DWORD dword_value = readValueOnRS485(); 
float temp = (float)dword_value; 

Ở đây, dword_value sẽ đi qua ở định dạng HEX như 0x4366C0C4 mà như một số thập phân sẽ được biểu diễn như 1130807492 nên typecasting này đến một phao chỉ đơn giản là mang lại cho tôi 1,130807492 * 10^9 hoặc 1130807492,0 đó không phải là điều tôi muốn.

tôi muốn duy nhất chính xác IEEE-754 đại diện mà sẽ cung cấp cho tôi một giá trị float của 230,75299072265625

Vì vậy typecasting rõ ràng nổi không làm việc cho tôi. Tôi cần một phương pháp có thể chuyển đổi hình thức này cho tôi. Tôi đã xem xét tất cả trong thư viện XC32 và tôi không thể tìm thấy bất cứ điều gì.

Có ai biết phương pháp được xác định trước thực hiện việc diễn giải này đúng cách cho tôi không? Hoặc là có lẽ một số phương pháp đề nghị tôi có thể viết? Tôi đang cố gắng để tránh viết mã của riêng tôi cho nhiệm vụ cụ thể này vì tôi lo lắng tôi không tìm thấy một giải pháp hiệu quả nếu C đã có một chức năng cho việc này.

Điều thú vị là, nếu tôi làm điều này để một char *, giá trị được biểu diễn trên char rằng * chính xác là 230,75:

sprintf(random_char_pointer, "%.2f, dword_value); 

Đây in random_char_pointer vào màn hình mang lại cho tôi 230,75 nên sprintf phải xử lý thông dịch cho tôi một cách chính xác. Vì vậy, tôi giả sử có một cái gì đó trong C đã cho tôi. Bất cứ ai có thể hỗ trợ?

+2

'f = * (float *) & uvalue;' (các cân nhắc liên kết cộng/trừ) – joop

+0

@joop Không tương đương với dàn diễn viên cho 'float'? – Downvoter

+1

Không, tôi bỏ một con trỏ int * unsigned * đến một con trỏ * * và dereference nó. – joop

Trả lời

7

Cách đề nghị để làm công cụ như thế này là sử dụng một công đoàn:

union { 
    DWORD w; 
    float f; 
} wordfloat; 

wordfloat.w = dword_value; 
temp = wordfloat.f; 

này làm những gì bạn muốn theo tiêu chuẩn ISO 9899: 2011 §6.5.2.3 ¶3 chú thích 95:

Biểu thức hậu tố theo sau là toán tử . và một số nhận dạng chỉ định một thành viên của một đối tượng cấu trúc hoặc công đoàn. Giá trị là giá trị của thành viên có tên, 95) và là một giá trị nếu biểu thức đầu tiên là một giá trị. Nếu biểu thức đầu tiên có loại đủ điều kiện, kết quả có phiên bản đủ điều kiện của loại thành viên được chỉ định.

95) Nếu thành viên được sử dụng để đọc nội dung của đối tượng công đoàn không giống như thành viên được sử dụng để lưu trữ giá trị trong đối tượng, phần thích hợp của biểu diễn đối tượng của giá trị được diễn giải lại dưới dạng đối tượng đại diện theo kiểu mới như được mô tả trong 6.2.6 (một quá trình đôi khi được gọi là "loại punning"). Đây có thể là một đại diện bẫy.

+0

Cảm ơn bạn FUZxxl sẽ thử điều này và cho bạn biết –

+0

Tôi tò mò, đề xuất 'dễ bay hơi' đến từ đâu? Khả năng làm kiểu tái giải dữ liệu này là một trong những lý do chính tại sao (thường, không bay hơi) 'union' tồn tại trong C. – user4815162342

+1

Không, biến động là không cần thiết (và về cơ bản vô nghĩa, bởi vì hai thành viên chia sẻ cùng một vị trí IIRC công đoàn không đảm bảo rằng hai thành viên thực sự chia sẻ chính xác cùng một địa điểm (liên kết hoặc kích thước của hai thành viên vẫn có thể khác nhau, giống như trong bình luận viết tắt của tôi) – joop

Các vấn đề liên quan