浮点到二进制值(C ++)

时间:2009-01-23 18:45:29

标签: c++ binary floating-point ieee-754

我想在C ++中使用浮点数,如2.25125,以及填充二进制值的int数组,该值用于将浮点数存储在内存中(IEEE 754)。

所以我可以取一个数字,最后得到一个带有二进制值的int num [16]数组: num [0]将为1 num [1]将为1 num [2]为0 num [3]将为1 等等...

将int放入数组并不困难,只是获取float的二进制值的过程就是我被困住的地方。你能不能在内存中读取float变量的二进制文件?如果没有,我怎么能用C ++做这个呢?

编辑:这种方式进行比较的原因是我想学习在C ++中进行按位操作。

13 个答案:

答案 0 :(得分:22)

使用union和bitset:

#include <iostream>
#include <bitset>

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

答案 1 :(得分:14)

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)将值1i位移到左侧。 &运算符计算操作数的按位和

对于float中的32位中的每一位,for循环运行一次。每次i都是我们想要从中提取值的位数。我们计算按位和数字1 << i

假设数字为:1001011,i = 2

1<<i将等于0000100

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

如果i = 3则:

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

基本上,结果将是i位设置为原始数字的i位且所有其他位为零的数字。结果将为零,这意味着原始数字中的i位为零或非零,这意味着实际数字的i位等于1

答案 2 :(得分:4)

其他方法,使用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;
}

答案 3 :(得分:2)

如果你需要一个特定的浮点表示,你必须从浮动本身语义构建它,而不是通过位复制。

c0x标准: http://c0x.coding-guidelines.com/5.2.4.2.2.html未定义浮点数的格式。

答案 4 :(得分:2)

  

你能不能在内存中读取float变量的二进制文件?

是。 Static将指向它的指针强制转换为int指针并从结果中读取位。 C ++中的IEEE 754 float类型是32位。

答案 5 :(得分:2)

您可以使用unsigned char将byte逐字节读取到整数数组中:

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));

答案 6 :(得分:2)

查看此答案中的注释(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";


}

答案 7 :(得分:1)

将int指针强制转换为浮点指针,然后就完成了。

(虽然我不会将它声明为int数组。我会使用void *来说明内存被用作其他值的转储基础。)

顺便说一下,你为什么不只使用一系列花车?

答案 8 :(得分:1)

创建float和unsigned long的并集。设置float成员的值并迭代无符号long值的位,如其他答案中所述。

这将消除演员操作。

答案 9 :(得分:0)

嗯,我不相信C ++有任何真正安全的方式存储浮动没有某种问题。当涉及到在机器之间移动时,既有效又容易存储而无需使用大容量存储容量。

这是非常准确的,但它不会支持真正疯狂的价值观。您可以在任何位置获得最多7位数字,但任何一方都不能超过7位数。对于左侧,您将收到不准确的结果。在右侧,您将在阅读时间内收到错误消息。要解决该错误,您可以在写入期间抛出错误或在读取时执行“buffer [idx ++]&amp; 0x7”以防止它超出0和7范围。请记住“&amp; 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);
}

答案 10 :(得分:0)

您也可以使用指针转换。这是一个小例子

#include <iostream>
#include <bitset>

using namespace std;

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

答案 11 :(得分:0)

这是我的不给出任何警告的解决方案:

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;
}

答案 12 :(得分:-1)

最简单的方法:

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