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