2013-05-24 33 views
10

Vì vậy, tôi đã tìm kiếm về chủ đề này và không tìm thấy gì thực sự liên quan về nó.Làm thế nào để chuyển đổi dấu chấm động thực sự được thực hiện trong C++? (Double to float hoặc float to double)

Tôi đã cố gắng để nhìn vào lắp ráp đằng sau mã đơn giản này:

int main(int argc, char *argv[]) 
{ 
    double d = 1.0; 
    float f = static_cast<float>(d); 

    system("PAUSE"); 
    return 0; 
} 

đó là (với Visual Studio 2012):

15:  double d = 1.0; 
000000013FD7C16D movsd  xmm0,mmword ptr [[email protected] (013FD91AB0h)] 
000000013FD7C175 movsd  mmword ptr [d],xmm0 
    16:  float f = static_cast<float>(d); 
000000013FD7C17B cvtsd2ss xmm0,mmword ptr [d] 
000000013FD7C181 movss  dword ptr [f],xmm0 

tôi không phải là thoải mái với lắp ráp nhưng cố gắng phân tích điều đó. Vì vậy, hai dòng đầu tiên dường như di chuyển giá trị chính xác kép 3ff0000000000000 vào sổ đăng ký, và sau đó di chuyển nội dung của thanh ghi đến địa chỉ bộ nhớ của d.

Sau đó, tôi chỉ không biết chính xác những gì các dòng tiếp theo. Các hoạt động cvtsd2ss rõ ràng là một hướng dẫn rằng convert double precision floating point value to single precision floating point value nhưng tôi không thể tìm thấy những gì hướng dẫn này thực sự. (Sau đó, giá trị được chuyển đổi được chuyển đến không gian bộ nhớ của f).

Câu hỏi của tôi là, chuyển đổi này thực sự được thực hiện như thế nào theo hướng dẫn này? Tôi biết rằng các diễn viên C++ sẽ mang lại giá trị gần nhất trong loại khác nhưng ngoài ra, tôi không có ý tưởng về các hoạt động thực tế ...

+0

"Tôi biết rằng diễn viên C++ sẽ mang lại giá trị gần nhất ở loại khác". Nhiều hơn những gì bạn cần biết? –

+0

[Hướng dẫn dành cho nhà phát triển phần mềm của Intel] (http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html) Tập 2. –

+1

Bạn có thể muốn đọc về nó trong [Tham khảo Kiến trúc Intel] (http://download.intel.com/products/processor/manual/325462.pdf) (Cảnh báo: PDF lớn), đặc biệt là bắt đầu từ trang 241. –

Trả lời

11

Hướng dẫn làm tròn của FPU để thực hiện chuyển đổi. Chế độ làm tròn mặc định là từ tròn đến gần nhất.

Để thực hiện theo thuật toán, nó giúp ghi nhớ thông tin tại IEEE 754-1985 Wikipedia page, đặc biệt là các biểu đồ thể hiện bố cục.

Thứ nhất, số mũ của các mục tiêu float được tính: loại double có một phạm vi rộng hơn float, vì vậy kết quả có thể 0.0f (hoặc một denormal) cho một rất nhỏ double, hoặc một giá trị vô hạn cho một rất lớn gấp đôi.

Đối với trường hợp thông thường là double được chuyển đổi thành số float bình thường (khoảng, khi số mũ không thiên vị của double có thể được thể hiện trong 8 bit của một biểu diễn chính xác), 23 bit đầu tiên của điểm đến có ý nghĩa và bắt đầu giống như ý nghĩa quan trọng nhất của định nghĩa 52 bit của số gốc.

Sau đó là vấn đề làm tròn:

  • nếu các bit còn sót lại dưới 10..0 thì significand mục tiêu còn lại như nó vốn có.

  • Nếu các bit còn lại ở trên 10..0, thì độ rộng mục tiêu được tăng lên. Nếu tăng nó làm cho nó tràn (vì nó đã là 1..1), sau đó mang được truyền vào bit số mũ. Điều này tạo ra kết quả chính xác vì cách bố trí IEEE 754 đã được thiết kế cẩn thận.

  • Nếu các bit còn lại chính xác là 10..0 thì double chính xác là giữa hai float s. Trong hai lựa chọn này, một lựa chọn có bit cuối cùng là 0 (“thậm chí”) được chọn.

Sau bước này, significand mục tiêu tương ứng với float gần với bản gốc double.

Chế độ làm tròn hướng dẫn chỉ đơn giản hơn. Trường hợp mục tiêu float là một sự bất thường phức tạp hơn một chút (người ta phải cẩn thận để tránh "làm tròn đôi").

+0

OK, nhưng trong mã trong câu hỏi, một đôi được chuyển đổi thành một đơn –

+0

@DavidHeffernan Oh, tôi sẽ sửa đổi câu trả lời. –

+1

Thậm chí chuyển đổi từ một đến hai cũng không thể di chuyển các bit. Giá trị bình thường yêu cầu thêm 896 vào số mũ. Các giá trị bất thường đòi hỏi phải tìm bit đầu tiên được thiết lập, thay đổi độ dài và điều chỉnh số mũ. –

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