簡體   English   中英

使用按位運算符比較浮點數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM