2009-07-15 64 views

Trả lời

1

Để thực sự giải thích nó, bạn có thể sẽ không muốn coi nó như là byte anyway bởi vì mantisa boundries không phù hợp với một 8bit boundry.

cái gì đó dọc theo dòng:

mantisa = (*(unsigned int *)&floatVal) | MANTISA_MASK; 
exp  = ((*(unsigned int *)&floatVal) | EXP_MASK ) >> EXP_SHIFT; 
sign = ((*(unsigned int *)&floatVal) | SIGN_MASK ) >> SIGN_SHIFT; 

sẽ cho phép bạn kéo nó ra để chơi với các trung tâm nước trái cây.

EDIT:

#include <stdio.h> 

    void main() 
    { 
    float a = 4; 
    unsigned int exp,sign,mantisa; 
    int i; 

     for(i = 0;i<4;i++) 
     { 
      exp  = (*((unsigned int *)&a) >>23) & 0xFF; 
      sign  = (*((unsigned int *)&a) >>31) & 0x01; 
      mantisa = (*((unsigned int *)&a)) & 0x7FFFFF | 0x800000; 

      printf("a  = %04x\r\n",*((unsigned int *)&a)); 
      printf("a  = %f\r\n",a); 
      printf("exp  = %i, %02x\r\n",exp,exp); 
      printf("sign = %i, %02x\r\n",sign,sign); 
      printf("mantisa = %i, %02x\r\n\r\n",mantisa,mantisa); 
      a = -a/2; 

     } 
    } 

Tạo:

a  = 40800000 
    a  = 4.000000 
    exp  = 129, 81 
    sign = 0, 00 
    mantisa = 8388608, 800000 

    a  = c0000000 
    a  = -2.000000 
    exp  = 128, 80 
    sign = 1, 01 
    mantisa = 8388608, 800000 

    a  = 3f800000 
    a  = 1.000000 
    exp  = 127, 7f 
    sign = 0, 00 
    mantisa = 8388608, 800000 

    a  = bf000000 
    a  = -0.500000 
    exp  = 126, 7e 
    sign = 1, 01 
    mantisa = 8388608, 800000 

    Press any key to continue . . . 
+0

Có, nhưng đây là hành vi không xác định (truy cập một giá trị float bằng cách sử dụng một con trỏ int). Bạn được bảo đảm để có thể truy cập các byte của một đối tượng như một mảng của unsigned char (trong C, ít nhất - tôi không chắc chắn về từ có thể so sánh trong tiêu chuẩn C++), nhưng không phải là các kiểu dữ liệu khác, nói chung . Đặc biệt, trình tối ưu hóa của trình biên dịch có quyền giả định rằng bạn chưa làm điều này và áp dụng các tối ưu hóa có thể phá vỡ mã của bạn nếu bạn có. – dewtell

+1

Ngoài ra, bạn cần phải lấy địa chỉ floatVal trước khi chuyển nó sang kiểu con trỏ khác. Ví dụ về những gì tôi đã nói về trình tối ưu hóa: nếu trình biên dịch đang giữ giá trị hiện tại của floatVal trong sổ đăng ký, trình tối ưu hóa sẽ có quyền giả định rằng nó không cần tràn giá trị hiện tại vào bộ nhớ trước khi thực thi mã này, vì những con trỏ int này không thể truy cập một cách hợp pháp giá trị float. Vì vậy, ngay cả khi hành vi không xác định đã không làm cho máy tính của bạn phát nổ, bạn có thể dễ dàng được chọn lên rác ngẫu nhiên thay vì giá trị mới nhất của floatVal với mã này. – dewtell

+0

Điều này hoạt động trên cả người lớn và nhỏ. – NoMoreZealots

14

Hãy thử liên kết này: http://en.wikipedia.org/wiki/IEEE_754

Tôi chỉ thấy rằng điều này có thể hữu ích hơn một chút: http://en.wikipedia.org/wiki/IEEE_754-1985

Đây là IEEE-tiêu chuẩn cho số dấu chấm động. Có một từ năm 1985 và một phiên bản sửa đổi từ năm 2008. Float là 32bit, double là 64bit (được giải thích trong liên kết thứ hai).


Edit: Thx để bình luận bởi Don, đây là liên kết để Intels mô tả 80bit điểm nổi: http://en.wikipedia.org/wiki/Extended_precision

+3

Tôi muốn thêm rằng đây là trường hợp áp đảo phổ biến, nhưng là sự lựa chọn bị ảnh hưởng bởi phần cứng là tốt. –

3

Nó cũng có thể là đáng chú ý là có một thành viên static bool const của std::numeric_limits, is_iec559, đó là tự nhiên chỉ có sẵn cho các loại điểm nổi. Tên là khá tự giải thích ...

+2

Tự giải thích miễn là bạn biết rằng IEC 559 là tên của sự tái chuẩn hóa theo ISO của cái được gọi là IEEE 754. Và bạn cũng nên biết rằng có thể có sai âm: tiêu chuẩn đó không chỉ là biểu diễn - - trong thực tế, tôi không chắc chắn rằng phiên bản 1985 yêu cầu một đại diện - nhưng cũng có hành vi (làm tròn, denormals, ...). Đặt thành viên đó thành sự thật ngụ ý rằng bạn tuân theo tất cả điều đó và sự khó khăn của một số nền tảng. Theo như tôi biết, các phiên bản Java đầu tiên bắt buộc nó và sau đó được hoàn nguyên khi hit hiệu suất quá cao. – AProgrammer

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