浮点到二进制值(C++)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/474007/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Floating Point to Binary Value(C++)
提问by user58389
I want to take a floating point number in C++, like 2.25125, and a int array filled with the binary value that is used to store the float in memory (IEEE 754).
我想在 C++ 中获取一个浮点数,如 2.25125,以及一个填充了用于将浮点数存储在内存中的二进制值的 int 数组(IEEE 754)。
So I could take a number, and end up with a int num[16] array with the binary value of the float: num[0] would be 1 num[1] would be 1 num[2] would be 0 num[3] would be 1 and so on...
所以我可以取一个数字,最后得到一个 int num[16] 数组,其中包含浮点数的二进制值: num[0] 将是 1 num[1] 将是 1 num[2] 将是 0 num[3 ] 将是 1 等等...
Putting an int into an array isn't difficult, just the process of getting the binary value of a float is where I'm stuck. Can you just read the binary in the memory that the float variable? If not, how could I go about doing this in C++?
将 int 放入数组并不困难,只是获取浮点数的二进制值的过程是我卡住的地方。你能在内存中读取浮点变量的二进制文件吗?如果没有,我怎么能在 C++ 中做到这一点?
EDIT: The reason for doing the comparison this way is that I am wanting to learn to do bitwise operations in C++.
编辑:以这种方式进行比较的原因是我想学习在 C++ 中进行按位运算。
回答by Martin York
Use union and bitset:
使用 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;
}
It may not be an array but you can access bits with [] operator as if you were using an array.
它可能不是数组,但您可以使用 [] 运算符访问位,就像使用数组一样。
Output
输出
$ ./bits
01000000000100000001010001111011
BIT 4: 1
BIT 7: 0
回答by Mehrdad Afshari
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;
Explanation
解释
(1 << i)
shifts the value 1
, i
bits to the left.
The &
operator computes the bitwise andof the operands.
(1 << i)
将值1
,i
位向左移动。该&
运算符计算操作数的按位和。
The for
loop runs once for each of the 32 bits in the float. Each time, i
will be the number of the bit we want to extract the value from. We compute the bitwise and of the number and 1 << i
:
的for
循环运行一次为每个在浮子32位的。每次,i
将是我们要从中提取值的位的编号。我们计算数字和的按位和1 << i
:
Assume the number is: 1001011, and i = 2
假设号码是:1001011,并且 i = 2
1<<i
will be equal to 0000100
1<<i
将等于 0000100
10001011
& 00000100
==========
00000000
if i = 3
then:
如果i = 3
那么:
10001011
& 00001000
==========
00001000
Basically, the result will be a number with i
th bit set to the i
th bit of the original number and all other bits are zero. The result will be either zero, which means the i
th bit in the original number was zero or nonzero, which means the actual number had the i
th bit equal to 1
.
基本上,结果将是一个数字,其中i
第 th 位设置为i
原始数字的第 th 位,所有其他位都为零。结果将是零,这意味着i
原始数字中的第 th 位为零或非零,这意味着实际数字的i
第 th 位等于1
。
回答by test30
other approach, using stl
其他方法,使用 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;
}
回答by Douglas Leeder
If you need a particular floating point representation, you'll have to build that up semantically from the float itself, not by bit-copying.
如果您需要特定的浮点表示,则必须从浮点本身在语义上构建它,而不是通过位复制。
c0x standard: http://c0x.coding-guidelines.com/5.2.4.2.2.htmldoesn't define the format of floating point numbers.
c0x 标准:http://c0x.coding-guidelines.com/5.2.4.2.2.html 没有定义浮点数的格式。
回答by codekaizen
Can you just read the binary in the memory that the float variable?
你能在内存中读取浮点变量的二进制文件吗?
Yes. Static cast a pointer to it to an int pointer and read the bits from the result. An IEEE 754 float
type in C++ is 32 bits.
是的。静态将指向它的指针转换为 int 指针并从结果中读取位。float
C++ 中的 IEEE 754类型是 32 位。
回答by Martin York
Looking at the comments in this answer (Floating Point to Binary Value(C++)) the reason to do this is to perform a bitwise comparison of two values.
查看此答案中的注释(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";
}
回答by Johannes Schaub - litb
You can use an unsigned char to read the float byte by byte into the integer array:
您可以使用无符号字符将浮点字节逐字节读入整数数组:
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.
By the way, if you just want to compare the bits (as you comment on another answer) use memcmp
:
顺便说一句,如果您只想比较这些位(当您评论另一个答案时),请使用memcmp
:
memcmp(&float1, &float2, sizeof (float));
回答by Noel Walters
Create a union of float and and unsigned long. set the value of the float member and iterate over the bits of the unsigned long value as already described in other answers.
创建 float 和 unsigned long 的联合。设置 float 成员的值并迭代 unsigned long 值的位,如其他答案中所述。
This will eliminate the cast operators.
这将消除强制转换运算符。
回答by benjismith
Cast the int pointer to a float pointer, and you're done.
将 int 指针转换为浮点指针,就大功告成了。
(Though I wouldn't declare it as an int array. I'd use void* to make it clear the the memory is being used as a dumping ground for other values.)
(虽然我不会将它声明为 int 数组。我会使用 void* 来明确表示内存被用作其他值的倾倒场。)
Incidentally, why don't you just use an array of floats?
顺便说一句,为什么不直接使用浮点数数组呢?
回答by Jeremy Trifilo
Well I don't believe C++ has any real safe way to store floats without some sort of issue. When it comes to moving between machines and is both efficient and easily stored without using a large storage capacity.
好吧,我不相信 C++ 有任何真正安全的方法来存储浮点数而不会出现某种问题。在机器之间移动时,既高效又易于存储,无需使用大存储容量。
It's very accurate, but it won't support really insane values. You will be able to have up to 7 digits in any location, but you can't exceed 7 digits on either side. For the left you'll receive inaccurate results. On the right you'll get an error during read time. To resolve the error you can throw an error during the write or perform "buffer[idx++] & 0x7" on the read to prevent it from going outside 0 and 7 bounds. Keep in mind "& 0x7" only works because it's a power of 2 minus one. Which is 2^3 - 1. You can only do that with those values E.g. 0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, etc...
它非常准确,但它不会支持真正疯狂的值。您最多可以在任何位置拥有 7 位数字,但任何一侧都不能超过 7 位数字。对于左侧,您将收到不准确的结果。在右侧,您将在读取期间收到错误消息。要解决该错误,您可以在写入期间抛出错误或在读取时执行“buffer[idx++] & 0x7”以防止其超出 0 和 7 边界。请记住,“& 0x7”之所以有效,是因为它是 2 减 1 的幂。这是 2^3 - 1。你只能用那些值来做到这一点,例如 0、1、3、7、15、31、63、127、255、511、1023 等......
So it's up to you if you want to use this or not. I felt it was a safe way to get most values you'll ever need. The example below shows how it's converted into a 4 byte array, but for C++ this would be a char*. If you don't want to perform division you can convert the POWERS_OF_TEN array into a secondary array with decimals and multiple instead.
因此,是否要使用它取决于您。我觉得这是获得大多数你需要的价值的安全方式。下面的示例显示了如何将其转换为 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);
}