[英]Comparing floats using bitwise operators
如何使用一系列按位運算比較浮點值?
別。 只是...不。 使用==
,或使用其狂野古怪的neigbors >
和<
。 甚至還有瘋狂的雜種, <=
和>=
! 這些應該可以滿足您所有的浮動比較需求。
更新:沒關系,不要使用==
。 其他應該沒問題。
更新更新:不使用==
意味着您可能也不應該使用<=
或>=
。 這個故事的寓意是,浮動是棘手的,這就是為什么您絕對不應該嘗試對它們進行按位操作。
實際上,在某些情況下按位操作浮點數是有意義的。 例如,如果您嘗試以較低的位精度或較高的位精度對硬件建模。 在這種情況下,您將需要訪問浮點數上的位。 正如bta所說,首先應該知道的是IEEE 754標准,這樣您就可以知道要操作的位。
然后,您可以使用諸如ShinTakezou的解決方案,但我建議您使用一些更復雜的方法。
假設我們要單精度。
首先,我們聲明一個具有不同浮點字段的結構:
typedef struct s_float{
int sign : 1;
int exponent : 8;
int mantissa : 23;
}my_float_struct;
那么我們就這樣聲明一個聯合:
union u_float{
float the_float;
my_float_struct the_structure;
}my_float;
然后我們可以通過執行以下操作來訪問代碼中的浮點數:
my_float.the_float = <float number>;
位字段的用法如下:
printf("%f is %d.%d.%d\n",my_float.the_float,my_float.the_structure.sign,my_float.the_structure.exponent,my_float.the_structure.mantissa);
而且,您可以分配,修改字段或其他所需的內容。
我不認為在float
上使用按位運算符會做您認為會做的事情。 在這樣做之前,請確保您熟悉IEEE 754標准,該標准控制內部浮點數的表示方式。 盡管這是完全有效的操作,但很有可能不是很有用。
您到底想完成什么? 可能有更好的方法。
float
表示的域與它們的位實現和操縱不太匹配。
您可以輕松地在浮點數上應用任何按位運算符,但不會獲得任何有用的信息,因為這些運算符將以某種方式修改數字,如果您要將其視為浮點數,則根本沒有任何意義。
對兩個指數進行“與”運算或對兩個尾數進行“異或”運算會有什么樣的意義? 我的意思是在實際的浮動操作中
浮點布局在很大程度上取決於平台。 我記得曾經看到過丑陋的駭客只使用整數運算來繪制隨機浮點數,但這絕對不是可移植的。
在非常罕見的情況下,您需要執行此操作(例如,處理外部浮點格式,例如在PC上操作的VAX G格式的數據),通常可以通過將浮點數據放入相同的大小,否則放入一個char數組(同樣,大小正確)。
不要期望這樣的代碼接近可移植或干凈的地方。 在典型情況下,您希望做的盡可能少,通常只需讀取原始數據,創建盡可能接近的本機浮點值,然后使用該值即可。 即使當/如果您必須處理此類外來數據,通常仍應避免進行外來格式的比較之類的操作。
在下面的鏈接中有一個很好的描述,該鏈接使用該技巧為浮點數創建了高度優化的排序功能。
http://www.stereopsis.com/radix.html
顯然,在大多數情況下,使用這種黑客工具不是可移植且不可取的。
如果您仔細閱讀有關fp編號的IEEE規范,那么您就開始了。 下一步是如果cpu具有fp支持,則在軟件中實現硬件已經完成的工作,否則,您必須從頭開始在軟件中實現fp操作(根據IEEE)...完全可行(這是必須要做的)如果需要使用IEEE 754,則在將IEEE用於cpus或fp協處理器之前執行此操作)。
讓我們假設您的目標根本無法執行fp,因此您需要從頭開始實現它。 然后由您決定如何將數字存儲在內存中(您是否可以同意系統的字節序); 例如,1.23的浮點數在我的機器(LE)上以0xA4709D3F的形式存儲在內存中,實際上,“正確”的方式是0x3F9D70A4(我們的寫入方式比LE更像BE,但是沒有“正確”方式...即使這種方式允許我們直接使用規格檢查數據,因此,如果我編寫-1.23,則將獲得0xBF9D70A4,很明顯,符號位已升為1)
但是,由於我們要從頭開始實現它,因此可以通過以下方式將數字寫入內存:
unsigned char p[4];
p[0] = 0x3f; p[1] = 0x9d; p[2] = 0x70; p[3] = 0xa4;
然后是困難的部分...像這樣:
bool is_positive(float_t *p)
{
return ! (p[0] & 0x80); // or alike
}
我們在內存中工作的前提是proc無法處理32位(或更多)整數。 當然,我選擇了更簡單的操作...! 其他的比較難,但是從IEEE 754描述開始並做一些推理,您可以實現所需的功能。 如您所見,這並不是那么容易...在某個地方,您可以找到沒有浮點數單元時就可以對fp數執行運算的庫,但是現在我卻找不到任何庫(例如Amiga mathieeedoubbas.library ,但是我認為您找不到此來源,無論如何它可能直接存在於m68k asm中;只是說軟件impl可能存在於某處...)
轉換為整數類型。 然后,您可以使用它的所有二進制操作。 當心轉換是暫時的(類型轉換就像一個函數返回值一樣,被解釋為具有不同的類型)。
float real_value;
(int)real_value | 3, // this will work
real_value | 3; // This will not work
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.