簡體   English   中英

浮點到二進制值(C++)

[英]Floating Point to Binary Value(C++)

我想在 C++ 中獲取一個浮點數,如 2.25125,以及一個填充了用於將浮點數存儲在內存中的二進制值的 int 數組(IEEE 754)。

所以我可以取一個數字,最后得到一個 int num[16] 數組,其中包含浮點數的二進制值: num[0] 將是 1 num[1] 將是 1 num[2] 將是 0 num[3 ] 將是 1 等等...

將 int 放入數組並不困難,只是獲取浮點數的二進制值的過程是我卡住的地方。 你能在內存中讀取浮點變量的二進制文件嗎? 如果沒有,我怎么能在 C++ 中做到這一點?

編輯:以這種方式進行比較的原因是我想學習在 C++ 中進行按位運算。

使用 union 和 bitset:

#include <iostream>
#include <bitset>
#include <climits>

int main()
{
    union
    {
        float input; // assumes sizeof(float) == sizeof(int)
        int   output;
    } data;

    data.input = 2.25125;

    std::bitset<sizeof(float) * CHAR_BIT> bits(data.output);
    std::cout << bits << std::endl;

    // or
    std::cout << "BIT 4: " << bits[4] << std::endl;
    std::cout << "BIT 7: " << bits[7] << std::endl;
}

它可能不是數組,但您可以使用 [] 運算符訪問位,就像使用數組一樣。

輸出

$ ./bits
01000000000100000001010001111011
BIT 4: 1
BIT 7: 0
int fl = *(int*)&floatVar; //assuming sizeof(int) = sizeof(float)

int binaryRepresentation[sizeof(float) * 8];

for (int i = 0; i < sizeof(float) * 8; ++i)
    binaryRepresentation[i] = ((1 << i) & fl) != 0 ? 1 : 0;

解釋

(1 << i)將值1向左移動i位。 of the operands. &運算符計算操作數的

for循環對浮點數中的 32 位中的每一個都運行一次。 每次, i將是我們想要從中提取值的位的編號。 我們計算數字和1 << i的按位和:

假設數字是:1001011,並且i = 2

1<<i將等於 0000100

  10001011
& 00000100
==========
  00000000

如果i = 3則:

  10001011
& 00001000
==========
  00001000

基本上,結果將是一個數字,其中第i位設置為原始數字的第i位,所有其他位都為零。 結果將是零,這意味着原始數字中的第i位為零或非零,這意味着實際數字的第i位等於1

其他方法,使用 stl

#include <iostream>
#include <bitset>

using namespace std;
int main()
{
    float f=4.5f;
    cout<<bitset<sizeof f*8>(*(long unsigned int*)(&f))<<endl;
    return 0;
}

如果您需要特定的浮點表示,則必須從浮點本身在語義上構建它,而不是通過位復制。

c0x 標准: http ://c0x.coding-guidelines.com/5.2.4.2.2.html 沒有定義浮點數的格式。

你能在內存中讀取浮點變量的二進制文件嗎?

是的。 靜態將指向它的指針轉換為 int 指針並從結果中讀取位。 C++ 中的 IEEE 754 float類型是 32 位。

您可以使用無符號字符將浮點字節逐字節讀入整數數組:

unsigned int bits[sizeof (float) * CHAR_BIT];
unsigned char const *c = static_cast<unsigned char const*>(
    static_cast<void const*>(&my_float)
);

for(size_t i = 0; i < sizeof(float) * CHAR_BIT; i++) {
    int bitnr = i % CHAR_BIT;
    bits[i] = (*c >> bitnr) & 1;
    if(bitnr == CHAR_BIT-1)
        c++;
}

// the bits are now stored in "bits". one bit in one integer.

順便說一句,如果您只想比較這些位(當您評論另一個答案時),請使用memcmp

memcmp(&float1, &float2, sizeof (float));

查看此答案中的注釋( Floating Point to Binary Value(C++) ),這樣做的原因是執行兩個值的按位比較。

#include <iostream>

int main()
{
    union Flip
    {
         float input;   // assumes sizeof(float) == sizeof(int)
         int   output;
    };

    Flip    data1;
    Flip    data2;
    Flip    data3;

    data1.input = 2.25125;
    data2.input = 2.25126;
    data3.input = 2.25125;

    bool    test12  = data1.output ^ data2.output;
    bool    test13  = data1.output ^ data3.output;
    bool    test23  = data2.output ^ data3.output;

    std::cout << "T1(" << test12 << ") T2(" << test13 << ") T3(" << test23 << ")\n";


}

將 int 指針轉換為浮點指針,就大功告成了。

(雖然我不會將它聲明為 int 數組。我會使用 void* 來明確表示內存被用作其他值的傾倒場。)

順便說一句,為什么不直接使用浮點數數組呢?

創建 float 和 unsigned long 的聯合。 設置 float 成員的值並迭代 unsigned long 值的位,如其他答案中所述。

這將消除強制轉換運算符。

您也可以使用強制轉換指針來實現。 這是一個小例子

#include <iostream>
#include <bitset>

using namespace std;

int main(){
    float f = 0.3f;
    int* p = (int*)&f;
    bitset<32> bits(*p);
    cout << bits << endl;
}

好吧,我不相信 C++ 有任何真正安全的方法來存儲浮點數而不會出現某種問題。 在機器之間移動時,既高效又易於存儲,無需使用大存儲容量。

它非常准確,但它不會支持真正瘋狂的值。 您最多可以在任何位置擁有 7 位數字,但任何一側都不能超過 7 位數字。 對於左側,您將收到不准確的結果。 在右側,您將在讀取期間收到錯誤消息。 要解決該錯誤,您可以在寫入期間拋出錯誤或在讀取時執行“buffer[idx++] & 0x7”以防止其超出 0 和 7 邊界。 請記住,“& 0x7”之所以有效,是因為它是 2 減 1 的冪。 即 2^3 - 1。您只能使用這些值來執行此操作,例如 0、1、3、7、15、31、63、127、255、511、1023 等...

因此,是否要使用它取決於您。 我覺得這是獲得大多數你需要的價值的安全方式。 下面的示例顯示了如何將其轉換為 4 字節數組,但對於 C++,這將是 char*。 如果您不想執行除法,您可以將 POWERS_OF_TEN 數組轉換為帶有小數和倍數的輔助數組。

const float CacheReader::POWERS_OF_TEN[] = 
{
    1.0F, 10.0F, 100.0F, 1000.0F, 10000.0F, 100000.0F, 1000000.0F, 10000000.0F
};

float CacheReader::readFloat(void)
{
    int flags = readUnsignedByte();
    int value = readUnsignedTriByte();
    if (flags & 0x1)
        value = -value;
    return value / POWERS_OF_TEN[(flags >> 1) & 0x7];
}

unsigned __int32 CacheReader::readUnsignedTriByte(void)
{
    return (readUnsignedByte() << 16) | (readUnsignedByte() << 8) | (readUnsignedByte());
}

unsigned __int8 CacheReader::readUnsignedByte(void)
{
    return buffer[reader_position] & 0xFF;
}

void CacheReader::writeFloat(float data)
{
    int exponent = -1;
    float ceiling = 0.0F;

    for ( ; ++exponent < 8; )
    {
        ceiling = (POWERS_OF_TEN[exponent] * data);
        if (ceiling == (int)ceiling)
            break;
    }

    exponent = exponent << 0x1;
    int ceil = (int)ceiling;
    if (ceil < 0)
    {
        exponent |= 0x1;
        ceil = -ceil;
    }
    buffer[writer_position++] = (signed __int16)(exponent);
    buffer[writer_position++] = (signed __int16)(ceil >> 16);
    buffer[writer_position++] = (signed __int16)(ceil >> 8);
    buffer[writer_position++] = (signed __int16)(ceil);
}

這是我的解決方案,沒有發出任何警告:

int32_t floatToIntBits(float f)
{
    char * c = (char*)&f;
    int32_t i = 0;
    i |= (int32_t)((c[3] << 24)     & 0xff000000);
    i |= (int32_t)((c[2] << 16)     & 0x00ff0000);
    i |= (int32_t)((c[1] << 8)      & 0x0000ff00);
    i |= (int32_t)((c[0])           & 0x000000ff);
    return i;
}

最簡單的方法:

float myfloat;
file.read((char*)(&myfloat),sizeof(float));

暫無
暫無

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

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