2010-05-05 41 views
23

Có cách nào để ánh xạ nổi vào int hoặc int không dấu để ngoại trừ NaN, thứ tự được giữ nguyên không?Bản đồ một phao 32 bit đến một số nguyên 32 bit

Vì vậy, nếu a và b là phao, và F là hàm ánh xạ,

một < b ám F (a) < F (b) và a == b ám F (a) == F (b)

+0

Vâng, tôi nghĩ rằng tôi đã nhìn thấy một ánh xạ như trước đây - nó được khá thông minh - Tôi chỉ ước tôi có thể nhớ * nơi * tôi đã thấy nó ... –

+0

Tôi có thể yêu cầu trường hợp sử dụng của bạn cho một bản đồ như vậy không? –

+3

+1 câu hỏi tuyệt vời –

Trả lời

12

Hm, chỉ cần xuất hiện trong quy trình DawsonCompare trong Lập trình trò chơi Đá quý 6, đó là một bit-cast bình thường theo sau là một dấu lật (kể từ khi nổi âm để đối diện với số nguyên âm). Tôi sẽ mượn ý tưởng đó.

Bạn có:

// utility 
template <typename R, typename T> 
R& bit_cast(T& pX) 
{ 
    return reinterpret_cast<R&>(pX); 
} 

// int32_t defined in <boost/cstdint.hpp>. 
boost::int32_t float_to_int_bits(float pX) 
{ 
    boost::int32_t x = bit_cast<boost::int32_t>(pX); 

    if (x < 0) 
     x = 0x80000000 - x; 

    return x; 
} 

Nếu bạn có thể đảm bảo bạn int là 32 bit, bạn chỉ có thể sử dụng.


Thực tế thú vị: Cuốn sách tiếp tục sử dụng này (lưu ý, không phải với mã chính xác tôi trình bày, kể từ khi tôi đã tách ra một phần float-to-int) để so sánh các giá trị dấu chấm động với sự khoan dung:

bool DawsonCompare(float pX, float pY, int pDiff) 
{ 
    int x = float_to_int_bits(pX); 
    int y = float_to_int_bits(pY); 

    int diff = x - y; 
    return abs(diff) < pDiff; 
} 

Điều này so sánh nổi như true nếu đại diện số nguyên của chúng nằm trong một phạm vi nhất định. (Anh ta sử dụng 1000 làm mặc định tốt). Phiên bản chi nhánh ít được gọi là LomontCompare được trình bày với cùng một ý tưởng, nhưng bạn phải mua sách đó. :)

+5

+1 đây là liên kết tuyệt vời có liên quan: http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm –

+1

Cảm ơn sự giúp đỡ – zounds

1

Chỉ cần để loại bỏ khả năng chậm if từ câu trả lời khác ...

int32_t float_to_int(float f) { 
    int32_t i = reinterpret_cast< int32_t& >(f); 
    uint32_t sgn = static_cast<uint32_t>(i) >> 31; 

    return i^-sgn & numeric_limits<int32_t>::max(); 
} 

Lưu ý rằng không giống như các giải pháp khác, điều này không đúng cách xử lý 0-0. Khi phao họ so sánh bằng nhau, nhưng sau khi ánh xạ tới số nguyên, chúng lần lượt trở thành 0-1. Như một trục trặc duy nhất trong dòng số, tôi không nghĩ rằng nó sẽ dễ dàng để xử lý trường hợp đó mà không có một hướng dẫn chi nhánh.

Tất nhiên, điều này giả hai của số học bổ sung, float là IEEE 754 duy nhất, cùng endianness và không gian địa chỉ tương tự cho phao nổi và ints vv

+0

Giải pháp của GMan xử lý 0 tích cực và tiêu cực một cách chính xác. –

+0

Ah, giờ tôi thấy, 'INT_MIN' =>' INT_MIN - INT_MIN'. Cảm ơn. – Potatoswatter

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