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).
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...
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++?
EDIT: The reason for doing the comparison this way is that I am wanting to learn to do bitwise operations in C++.
Use union and 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;
}
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
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 and of the operands.
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
:
Assume the number is: 1001011, and i = 2
1<<i
will be equal to 0000100
10001011
& 00000100
==========
00000000
if i = 3
then:
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
.
other approach, using 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;
}
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.html doesn't define the format of floating point numbers.
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(&float1, &float2, sizeof (float));
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.
#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";
}
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.
Cast the int pointer to a float pointer, and you're done.
(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.)
Incidentally, why don't you just use an array of floats?
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.
This will eliminate the cast operators.
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.
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...
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.
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);
}
Easiest way:
float myfloat;
file.read((char*)(&myfloat),sizeof(float));
来源:https://stackoverflow.com/questions/474007/floating-point-to-binary-valuec