簡體   English   中英

C ++:清除單個精度浮點的位

[英]C++: Clear bits of a single precision float

我目前正在將原本打算用於OpenCL的程序轉換為C ++,但其中的某個特定部分有些麻煩。

所述程序中常用的一種表達方式是采用32位浮點數,將其轉換為整數(即​​,實際上不將其舍入為int,而是將相同的數據解釋為int-請考慮reinterpret_cast),執行一些魔術操作。然后將其轉換回浮點數(再次,不是實際轉換,而是對相同數據的重新解釋)。 盡管這在OpenCL中運行良好,但使用C ++和gcc卻違反了嚴格的別名規則,如果啟用了優化,則會破壞程序,並且由於體系結構的不同,由於浮點數和整數寄存器是分開的,因此可能涉及昂貴的加載命中存儲。

我已經能夠有效地避免大多數這些表達式,但是我不確定其中是否可以更快地完成。 基本上,目的是清除浮點數右邊的一些位; OpenCL代碼與此類似:

float ClearFloatBits(float Value, int NumberOfBits) {
    return __int_as_float((__float_as_int(Value) >> NumberOfBits) << NumberOfBits);
}

由於這實際上是從指定的(二進制)數字取整,因此我的C ++版本現在看起來像這樣:

float ClearFloatBits(float Value, int NumberOfBits) {
    float Factor = pow(2.0f, 23 - NumberOfBits);

    return ((int)(Value*Factor))/Factor;
}

當然, pow和除法用LUT查找和相應的乘法代替,此處出於更好的可讀性而省略。

有一個更好的方法嗎? 特別令我煩惱的是要舍入的(int)轉換,我認為這是最昂貴的部分。 如果有幫助,可以保證傳遞給函數的浮點數是介於1.0(含)和2.0(不含)之間的數字。

提前致謝

請改用Union Hack:

float ClearFloatBits(float Value, int NumberOfBits) {
   union { unsigned int int_val; float flt_val; } union_hack;
   union_hack.flt_val = Value;
   (union_hack.int_val >>= NumberOfBits) <<= NumberOfBits;
   return union_hack.flt_val;
}

嚴格來說,這是未定義的行為。 根據C和C ++標准, 將寫入 結果寫入聯盟的一個成員然后從另一個成員讀取而不先寫入另一個成員是未定義的, 這是非法的

但是,這種聯合的用法是如此廣泛和古老,以至於我所認識的編譯器作者都沒有遵守該標准。 在實踐中,行為定義得很清楚,正是您所期望的。 就是說,如果將該hack移植到使用非常嚴格符合要求的編譯器的某些非常奇怪的體系結構計算機上,則可能無法正常工作。

重新解釋為int違反別名規則。 重新解釋為unsigned char[4]不會。 您是否需要支持NumberOfBits值> = 8? 如果沒有,您可以在ptr[3]上進行ptr[3]

您不能使用floor()而不是轉換為int嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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