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

问题描述 投票:0回答:14

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

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

将 int 放入数组中并不困难,只是获取 float 的二进制值的过程是我遇到困难的地方。你可以只读取内存中的浮点变量的二进制吗?如果没有,我怎样才能用 C++ 来做这个呢?

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

c++ binary floating-point ieee-754
14个回答
32
投票

使用联合和位集:

#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

15
投票
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
位向左移动。
&
运算符计算操作数的 按位与

for
循环对浮点数中的每个 32 位运行一次。每次,
i
将是我们要从中提取值的位数。我们计算数字的按位与 和
1 << i
:

假设号码是:1001011,并且

i = 2

1<<i
将等于 0000100

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

如果

i = 3
那么:

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

基本上,结果将是一个数字,其中第

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


6
投票

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

2
投票

如果您需要特定的浮点表示形式,则必须从浮点本身语义上构建它,而不是通过位复制。

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


2
投票

您可以使用无符号字符将浮点数逐字节读取到整数数组中:

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

2
投票

查看此答案中的注释(浮点到二进制值(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";


}

2
投票

可以直接读取内存中的float变量的二进制吗?

是的。将指向它的指针静态转换为 int 指针并从结果中读取位。 C++ 中的 IEEE 754

float
类型是 32 位。


1
投票

将 int 指针转换为 float 指针,就完成了。

(虽然我不会将其声明为 int 数组。我会使用 void* 来明确内存正被用作其他值的垃圾场。)

顺便说一句,为什么不直接使用浮点数组呢?


1
投票

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

这将消除强制转换运算符。


1
投票

您也可以通过强制转换指针来完成此操作。这是一个小例子

#include <iostream>
#include <bitset>

using namespace std;

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

0
投票

我不相信 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);
}

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

0
投票

使用模板

union
static_assert
可以在
float
double
之间进行转换:

template<typename F,typename I>
union _f2i {
    const F f;
    const I i;
    _f2i(F f) : f{f} { }
    _f2i(I i) : i{i} { }
    static_assert(sizeof(F) == sizeof(I), "Incompatible float/integer types");
};

然后您决定

float
double
转换:

//uint64_t test = f2i<double,uint32_t>{31.7}.i; // Assertion error at compile time

using f2i = _f2i<float,uint32_t>;
using d2i = _f2i<double,uint64_t>;

uint32_t intr = f2i{31.7f}.i;
float    fltr = f2i{uint32_t(0x41FD999A)}.f;
std::cout << std::hex << intr << std::endl;
std::cout << fltr << std::endl;

uint64_t lintr = d2i{31.7}.i;
double   dblr  = d2i{uint64_t(0x403FB33333333333)}.f;
std::cout << std::hex << lintr << std::endl;
std::cout << dblr << std::endl;

给予:

41fd999a
31.7
403fb33333333333
31.7

-1
投票

最简单的方法:

float myfloat;
file.read((char*)(&myfloat),sizeof(float));
© www.soinside.com 2019 - 2024. All rights reserved.