0

Is there a way i could initialize a float type variable with hexadecimal number? what i want to do is say i have single precision representation for 4 which is 0x40800000 in hex. I want to do something like float a = 0x40800000 in which case it takes the hex value as integer. What can i do to make it treat as floating point number?

Gautam
  • 375
  • 2
  • 6
  • 23
  • @KarolyHorvath the number i get will be in hexadecimal represented in single/double precision floating point format. – Gautam Jan 21 '15 at 12:57
  • Put the integer together with a float in a union. – Some programmer dude Jan 21 '15 at 12:58
  • @JoachimPileborg Thanks i was thinking of doing it but i read somewhere that such use is undefined. Can i safely use it? – Gautam Jan 21 '15 at 12:59
  • @Gautam: pure curiosity, but why do you get it in that format? this all happens at compliation time, I cannot imagine a scenario... – Karoly Horvath Jan 21 '15 at 12:59
  • What is the question about? Do you want to init the float var to a value of 4 which is in binary representation on YOUR SYSTEM a hex value of 0x40800000 ? If so, you are writing non portable code. And also you can write just `float a=4;` If this is not your question, what do you want to achieve? – Klaus Jan 21 '15 at 13:00
  • Read about [type punning](http://en.wikipedia.org/wiki/Type_punning), it's well-defined but not generally portable (you can't e.g. get the "integer" value of a `float` and send it over a socket to another platform). – Some programmer dude Jan 21 '15 at 13:02
  • 2
    @Gautam: It's implementation-defined. Nothing wrong with doing it, but it theoretically limits portability to systems few people currently use and systems that don't yet exist. If you're trying to specify floating-point numbers in a more sensible notation, lots of compilers support C99 hexfloats---`0x1.0p+2` is 4, and `0x1.5555555555555p+0` is roughly 4/3. – tmyklebu Jan 21 '15 at 13:13
  • @KarolyHorvath I was trying to see if i the floating point result obtained by simulating a ARMv7 floating point instruction will match the result i compute in my computer running c program. The result of simulation is in hex. so i thought if it would be possible to initialize the float variable directly with hex – Gautam Jan 21 '15 at 13:19
  • @Klaus I get the number in hex format. They are in single or double precision floating point format. Actually i get these numbers from running simulation and i want to use the number directly to initialize a float variable and avoiding conversion to decimal then initialize. – Gautam Jan 21 '15 at 13:28
  • 2
    @Gautam: If that's all that's going on, do input and output in C99 hexfloat format instead. – tmyklebu Jan 21 '15 at 14:26
  • @tmyklebu Thaks for the pointer. I will try try hexfloat and see – Gautam Jan 21 '15 at 14:51
  • As far as I know C99 hexfloats are *not* part of the current C++ standard [this question is tagged C++], but may be supported as a compiler vendor extension. – njuffa Jan 21 '15 at 18:48

3 Answers3

2

One option is to use type punning via a union. This is defined behaviour in C since C99 (previously this was implementation defined).

union {
  float f;
  uint32_t u;
} un;
un.u = 0x40800000;
float a = un.f;

As you tagged this C++, you could also use reinterpret_cast.

uint32_t u = 0x40800000;
float a = *reinterpret_cast<float*>(&u);

Before doing either of these, you should also confirm that they're the same size:

assert(sizeof(float) == sizeof(uint32_t));
Community
  • 1
  • 1
Simon Byrne
  • 7,694
  • 1
  • 26
  • 50
  • 1
    How do you use `reinterpret_cast` here? – TonyK Jan 21 '15 at 13:46
  • @TonyK He's saying don't use the C-style casts in the link, use `reinterpret_cast`. – Jonathan Mee Jan 21 '15 at 13:51
  • @JonathanMee: Maybe he's saying that (e.g. `f = *reinterpret_cast(&i)`). But then you don't need unions at all. And why "also"? – TonyK Jan 21 '15 at 14:07
  • @TonyK Yes, that was what I had in mind. The union suggestion was for pure C: "also" should be read as "alternatively". – Simon Byrne Jan 21 '15 at 14:11
  • 2
    The sentence “This is defined behaviour in C since C99” makes it sound like C99 started to allow type-punning through unions, when in fact, type-punning through unions is allowed **in all C standards**; what happened is only that C99 was unfortunately unclear on the fact that type-punning through unions was allowed, until TC3 clarified the situation. C89 says “if a member of a union object is accessed after a value has been stored in a different member of the object, the behavior is implementation-defined” which is absolutely unambiguous. – Pascal Cuoq Jan 21 '15 at 14:16
  • @SimonByrne I think it would be helpful if you made this more than a link answer. Otherwise this is less helpful than [Joachim Pileborg](http://stackoverflow.com/users/440558/joachim-pileborg)'s comments. [TonyK](http://stackoverflow.com/users/428857/tonyk)'s point is a good one, it's unclear what you're saying with `reinterpret_cast`. – Jonathan Mee Jan 21 '15 at 14:17
  • 1
    This question is marked [C++]. As far as I am aware, type-punning via union is "legal" C99, but not supported by C++, where `memcpy()` must be used for bit-wise transfers between different types in a standard-compliant way. – njuffa Jan 21 '15 at 18:53
1

You can do this if you introduce a temporary integer type variable, cast it to a floating point type and dereference it. You must be careful about the sizes of the types involved, and know that they may change. With my compiler, for example, this works:

unsigned i = 0x40800000;
float a = *(float*)&i;
printf("%f\n", a);
// output 4.00000
MuertoExcobito
  • 9,741
  • 2
  • 37
  • 78
  • While this might work, I'm pretty sure it's undefined behaviour as per the spec, so beware dragons and all that. – Simon Byrne Jan 21 '15 at 13:41
  • @SimonByrne This is identical to using a `union` provided that `sizeof(unsigned) == sizeof(float)`, so maybe there should be an `assert` there. – Jonathan Mee Jan 21 '15 at 13:48
  • 3
    @JonathanMee No, one is undefined behavior in C and the other is not. This means that the compiler can and will optimize assuming that `*(float*)&i` does not happen. C and C++ compilers ceased to be line-by-line translators from source to assembly about fifteen years ago (http://www.drdobbs.com/cpp/type-based-alias-analysis/184404273 ) – Pascal Cuoq Jan 21 '15 at 14:21
  • @PascalCuoq That is a very interesting article. Thank you. As it pertains to these answers though, as long as `a` is not a `float*` there should be no problems in C++ using this cast instead of a `union`. – Jonathan Mee Jan 21 '15 at 15:49
1

I'm not sure how you're getting your the value "0x40800000".

If that's coming in as an int you can just do:

const auto foo = 0x40800000;
auto a = *(float*)&foo;

If that's coming in as a string you can do:

float a;

sscanf("0x40800000", "0x%x", &a);
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • 0x40800000 is what the in-memory binary representation of 4 looks like in IEEE 754 format. See [this](http://www.h-schmidt.net/FloatConverter/IEEE754.html) for an interactive example. If, for example you were writing a low level, architecture specific, cycle-optimized deserializer for 32-bit IEEE754 then you could do what you're suggesting in your first example. – Andy Brown Jan 21 '15 at 13:53
  • @AndyBrown My, along with all the other current answers simply assume that an `int` is the same size as a `float`, *and* that the `float` represented by "0x40800000" is of the same format as used by the current architecture. As long as both of these are true, it is not necessary to write a deserializer. A simple `union` or cast is sufficient. – Jonathan Mee Jan 21 '15 at 14:06