views:

326

answers:

7

Hi,

I'm wondering if there is a way to represent a float using a char in C++?

For example:

int main()  
{  
    float test = 4.7567;  
    char result = charRepresentation(test);  
    return 0;  
}  

I read that probably using bitset I can do it but I'm not pretty sure.

Let's suppose that my float variable is 01001010 01001010 01001010 01001010 in binary.

If I want a char array of 4 elements, the first element will be 01001010, the second: 01001010 and so on.

Can I represent the float variable in a char array of 4 elements?

+1  A: 

the best you can is create custom float that is byte size. or use char as fixed point decimal. on all cases this will lead to significant loss of precision.

Andrey
Although the precision loss may be inconsequential, depending on the data requirements. E.g. 8 bits is able to represent 1.0 and 0.0 and 254 steps in between if that's all you need.
dash-tom-bang
A: 

You can only do so partially in a way that won't allow you to fully recover the original float. In general, this is called Quantization, and depending on your requirements there is an art to picking a good quantization. For example, floating point values used to represent R, G and B in a pixel will be converted to a char before being displayed on a screen.

Alternatively, it's easy to store a float in its entirety as four chars, with each char storing some of the information about the original number.

A: 

You can create, for that number, a fixed point value using 2 bits for the whole number and 5 bits for the fractional portion (or 6 if you want it to be unsigned). That would be able to store roughly 4.76 in terms of accuracy. You don't quite have enough size to represent that number much more accurately - unless you used a ROM lookup table of 256 entries where you are storing your info outside the number itself and in the translator.

Michael Dorgan
+7  A: 

I suspect what you're trying to say is:

int main()  
{  
    float test = 4.7567; 
    char result[sizeof(float)];

    memcpy(result, &test, sizeof(test));

    /* now result is storing the float,
           but you can treat it as an array of 
           arbitrary chars

       for example:
    */
    for (int n = 0; n < sizeof(float); ++n) 
        printf("%x", result[n]);

    return 0;  
}  

Edited to add: all the people pointing out that you can't fit a float into 8 bits are of course correct, but actually the OP is groping towards the understanding that a float, like all atomic datatypes, is ultimately a simple contiguous block of bytes. This is not obvious to all novices.

egrunin
I'd add something to this to explain that "sizeof" is working out how many chars you can fit in a float, and that you get back several chars as your result.
deworde
You can also use reinterpret_cast<char*>(test) to similar effect.
starblue
If a float takes 32 bits and a char takes 8 bits, can I divide the entire float in 4 pieces, I mean, a char array of 4 elements?
Eric
@Eric: That is exactly what egrunin is doing. The code creates a char array of however many elements are necessary, and copies in the float. If this isn't what you're looking for, what is?
David Thornley
@David but it will return an array of 20 elements in this case, right? ffffffe336ffffff9840, can the float be represented in only 4 elements?
Eric
I see your confusion... the char is not containing one hex character, it's containing 8 bits (which, through ASCII, map to some arbitrary characters).
rmeador
roe
though, `union { float f; char c[sizeof(float)]; }` is a little shorter to write, and more to the point.
roe
This is an important fundamental to grasp, but don't write code like this if you can avoid it. The translation from float to bytes varies from platform to platform. See http://en.wikipedia.org/wiki/Endianness.
Potatoswatter
starblue
@Eric: The hex number you gave was considerably more than four bytes (I'm not bothering to count), and hence will not fit in four characters on most systems in use today. On every system I've got access to today, a float is 32 bits and a char is 8. If you have a system where sizeof(float) > 4, you'll need more characters to hold it.
David Thornley
A: 
int main()  
{  
    float test = 4.7567;  
    char result = charRepresentation(test);  
    return 0;  
}

If we ignore that your float is a float and convert 47567 into binary, we get 10111001 11001111. This is 16 bits, which is twice the size of a char (8 bits). Floats store their numbers by storing a sign bit (+ or -), an exponent (where to put the decimal point, in this case 10^-1), and then the significant digits (47567). There's just not enough room in a char to store a float.

Alternatively, consider that a char can store only 256 different values. With four decimal places of precision, there are far more than 256 different values between 1 and 4.7567 or even 4 and 4.7567. Since you can't differentiate between more than 256 different values, you don't have enough room to store it.

You could conceivably write something that would 'translate' from a float to a char by limiting yourself to an extremely small range of values and only one or two decimal places*, but I can't think of any reason you would want to.

*You can store any value between 0 and 256 in a char, so if you always multiplied the value in the char by 10^-1 or 10^-2 (you could only use one of these options, not both since there isn't enough room to store the exponent) you could store any number between 0 and 25.6 or 0 and 2.56. I don't know what use this would have though.

Joel
A: 

A C char is only 8 bits (on most platforms). The basic problem this causes is two-fold. First, almost all FPUs in existence support IEEE floating point. That means floating point values either require 32 bits, or 64. Some support other non-standard sizes, but the only ones I'm aware of are 80 bits. None I have ever heard of support floats of only 8 bits. So you couldn't have hardware support for an 8-bit float.

More importantly, you wouldn't be able to get a lot of digits out of an 8-bit float. Remember that some bits are used to represent the exponent. You'd have almost no precision left for your digits.

Are you perhaps instead wanting to know about Fixed point? That would be doable in a byte.

T.E.D.
The standard (IEEE 754-2008) sizes also include half-precision (16-bit) and quadruple-precision (128-bit). There's no 8-bit, though.
dan04
A: 
dwelch
using `union` this way is undefined behavior.
Cubbi
do I have a bug? this wasnt fully tested code, just a "try something like this without the bugs" kind of code, just like the posters, kind of like this but ignore the bugs code. I have been using a union to examine floating point bits for years, various compilers, various platforms, never had one issue. At least in C, do unions not work with C++?
dwelch
Actually the memcpy approach can fail for the same reason the pointer to memory approach can fail, if you want to avoid undefined behaviors in compilers you have to go beyond the reach of the compiler like writing to a file for example. If you are comfortable with less than 100% reliable, any of these approaches will work.
dwelch